自定义控件的构建(6)
前面讲到了视图和控件状态,ASP.NET中有个概念叫做回传,因为ASP.NET框架是围绕Web表单构建的,回传即信息从客户端浏览器传递到服务器的过程。
那么这其中又分为2种情况:
当控件引起回传的时候,表单回传到服务器,会引发服务器控件,比如Button被单击时,Click事件则会再包含该Button的表单中回传给服务器,这也称为回传事件。
第2种情况则是,Web表单中的数据也可以传给控件。比如当表单包含TextBox时,表单中的数据会在Web表单提交到服务器时传递给TextBox,这个数据又称为回传数据。
下面分别说明这2种情况的实现
处理回传数据
这里主要使用到IPostBackDataHandler接口
namespace HandlePostBack
{//处理回传数据
public class HandlePostDataControl:WebControl,IPostBackDataHandler{public event EventHandler TextChanged;public string Text{get
{if (ViewState["Text"] == null)return String.Empty;
else
return (string)ViewState["Text"];}set
{ViewState["Text"] = value;}}protected override void AddAttributesToRender(HtmlTextWriter writer){writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");
writer.AddAttribute(HtmlTextWriterAttribute.Value, Text);writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID);
base.AddAttributesToRender(writer);
}public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection){if (postCollection[postDataKey] != Text)
{Text = postCollection[postDataKey];return true;}return false;}protected override HtmlTextWriterTag TagKey{get
{return HtmlTextWriterTag.Input;
}}public void RaisePostDataChangedEvent(){if (TextChanged != null){TextChanged(this, EventArgs.Empty);
}}}}
IPostBackDataHandler接口包括两个方法:LoadPostData用来检索从浏览器传回的表单域,其中第一个参数表示关联到当前控件的域的名字,RaisePostDataChangedEvent用来引发指示一个表单域值发生改变的事件,这里注意一点:如果表单域的名字与控件名字不匹配,则要实现上面的功能时,需要在控件的PreRender事件中调用Page.RegiseterRequiresPostBack(),通知页面这个控件有兴趣回收这个回传数据
上面的代码主要是让TextBox在页面回传中保存输入框的状态,并且在内容被修改后引发TextChanged事件,如果表单域的值和控件Text属性值不匹配,那么将更新Text属性并且返回True值,当LoadPostData返回True值时,就会执行RaisePostDataChangedEvent,一般都用这个方法实现一个事件。
处理回传事件
一次只能由一个控件引发表单提交至服务器的行为,同回传数据一样,其需要实现IPostBackEventHandler接口,这个接口包含了RaisePostBackEvent事件,用于控件引发回传时在服务器调用
namespace {
public class HandlePostEventControl : WebControl, IPostBackEventHandler{private string _Text;public string Text{get { return _Text; }set { _Text = value; }}public event EventHandler Click;protected override void AddAttributesToRender(HtmlTextWriter writer){string eRef = Page.ClientScript.GetPostBackClientHyperlink(this, String.Empty);writer.AddAttribute(HtmlTextWriterAttribute.Href, eRef);base.AddAttributesToRender(writer);
}protected override HtmlTextWriterTag TagKey{get
{return HtmlTextWriterTag.A;
}}protected override void RenderContents(HtmlTextWriter writer){writer.Write(_Text);}public void RaisePostBackEvent(string eventArgument){if(Click!=null){Click(this, EventArgs.Empty);
}}}}
这段代码主要示例了如何实现IPostBackEventHandler接口,这个自定义控件类似于LinkButton,在浏览器中单击该控件生成的连接时,包含该控件的表单就会
回传给服务器并调用RaisePostBackEvent()
这里需要注意的是AddAttributesToRender()中第一行代码,GetPostBackClientHyperlink()用于返回浏览器中引起表单回传的JS,它返回类似下面的js代码
javascript:_doPostBack('HandlePostEventControl1','') ;_doPostBack()用于调用客户端表单的submit().代码演示:
后台代码:<%@ Page Language="C#" AutoEventWireup="true" CodeFile="TextPostBackControl.aspx.cs" Inherits="TextPostBackControl" %>
<%@ Register TagPrefix="handleps" Namespace="HandlePostBack" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"><title></title></head><body><form id="form1" runat="server"><div><asp:TextBox ID="TextBox1" runat="server"></asp:TextBox><asp:Label ID="Label2" runat="server" Text="Label" EnableViewState="false"></asp:Label><handleps:HandlePostEventControl ID="HandlePostEventControl1" runat="server" Text="submit" OnClick="EventControl1_Click" /></div></form></body></html>
当单击这个自定义的按钮时,Click事件会将TextBox中的值显示在Label中protected void EventControl1_Click(object sender, EventArgs e){this.Label2.Text = HandlePostEventControl1.Text;
}
本文参考了《ASP.NET 揭秘(卷2)》