我只是上述控件例了,为了说明IPostBackEventHandler应用场合,但上述例子中的事件处理没有得到优化,因为它为每个委托实例生成一个字段,当控件上定义了很多事件时,就会增加存储成本,基类 System.Web.UI.Control 为存储和检索事件委托提供了更有效的数据结构(通过其 Events 属性)。Events 属性的类型为 EventHandlerList,该类型是为有效存储和检索事件委托而设计的数据结构;我把优化了的事件处理贴上来,看看:
代化事件后
1using System;
2using System.Data;
3using System.Configuration;
4using System.Web;
5using System.Web.Security;
6using System.Web.UI;
7using System.Web.UI.WebControls;
8using System.Web.UI.WebControls.WebParts;
9using System.Web.UI.HtmlControls;
10using System.ComponentModel;
11///
12/// IPostBackEventHandler示例
13///
14///
15namespace cnblogs.suiqirui
16{
17 [DefaultEvent("Click")]
18 [DefaultProperty("Text")]
19 public class buttonevent1 : WebControl, IPostBackEventHandler
20 {
21 private static readonly object ClickEvent = new object();
22 public event EventHandler Click
23 {
24
25 add
26 {
27
28 Events.AddHandler(ClickEvent, value);
29 }
30 remove
31 {
32 Events.AddHandler(ClickEvent, value);
33 }
34 }
35 [Bindable(true)]
36
37
38 public virtual string Text
39 {
40
41 get
42 {
43 string s = (string)ViewState["Text"];
44 return ((s == null) ? "" : s);
45
46 }
47 set
48 {
49
50 ViewState["Text"] = value;
51 }
52
53 }
54 protected override HtmlTextWriterTag TagKey
55 {
56 get
57 {
58 return HtmlTextWriterTag.Input;
59 }
60 }
61 protected override void AddAttributesToRender(HtmlTextWriter writer)
62 {
63 base.AddAttributesToRender(writer);
64 writer.AddAttribute("Name", this.UniqueID);
65 writer.AddAttribute("Type", "submit");
66 writer.AddAttribute(HtmlTextWriterAttribute.Value, this.Text);
67 }
68 public void RaisePostBackEvent(string eventArgument)
69 {
70
71 onClick(new EventArgs());
72 }
73
74 protected virtual void onClick(EventArgs e)
75 {
76 EventHandler clickEventDel = Events[ClickEvent] as EventHandler;
77 if (clickEventDel != null)
78 { clickEventDel(this, e); }
79 }
80 protected override void Render(HtmlTextWriter writer)
81 {
82 if (Page != null)
83 {
84 Page.VerifyRenderingInServerForm(this); //确保此控件在form表单内
85 }
86 base.Render(writer);
87 }
88 public buttonevent1()
89 {
90 }
91 }
92}
到此为此,讲完了第一个事件处理IPostBackEventHandler
第二个:IPostBackDataHandler 该接口用于处理客户端引发的页面回传的事件,实现此接口,服务器可将客户端的提交表单事件对应到服务器的事件上,并且通过事件上,并且通过事件处理程序完成对该客户端事个把的处理. 如果希望设计的服务器控件检查客户端回发到服务器的窗体数据,则必须实现 IPostBackDataHandler 接口。该接口定义的合同允许服务器控件确定其状态是否在回发发生后更改,并引发适当的事件 该接口有两个方法.
该接口表述如下:
1Public interface IPostBackDataHandler{
2
3bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection);// 为 ASP.NET 服务器控件处理回发数据。
4
5void RaisePostDataChangedEvent();//要求服务器控件对象通知 ASP.NET 应用程序该控件的状态已更改
6
7}
8
LoadPostData方法。如果服务器控件的状态在回发发生后更改,则为 true;否则为 false
示例:
LoadPostData示例
public virtual bool LoadPostData(string postDataKey,
NameValueCollection postCollection) {
String presentValue = Text;
String postedValue = postCollection[postDataKey];
if (presentValue == null || !presentValue.Equals(postedValue)){
Text = postedValue;
return true;
}
return false;
}
RaisePostDataChangedEvent实现该接口的服务器控件的更改事件(如果有)从此方法引发。
示例:
public virtual void RaisePostDataChangedEvent() {
OnTextChanged(EventArgs.Empty);
}
控件代码:
控件示例
1using System;
2using System.Web;
3using System.Web.UI;
4using System.Collections;
5using System.Collections.Specialized;
6
7
8namespace CustomWebFormsControls {
9
10 [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]
11 public class MyTextBox: Control, IPostBackDataHandler {
12
13
14 public String Text {
15 get {
16 return (String) ViewState["Text"];
17 }
18
19 set {
20 ViewState["Text"] = value;
21 }
22 }
23
24
25 public event EventHandler TextChanged;
26
27
28 public virtual bool LoadPostData(string postDataKey,
29 NameValueCollection postCollection) {
30
31 String presentValue = Text;
32 String postedValue = postCollection[postDataKey];
33
34 if (presentValue == null || !presentValue.Equals(postedValue)) {
35 Text = postedValue;
36 return true;
37 }
38
39 return false;
40 }
41
42
43 public virtual void RaisePostDataChangedEvent() {
44 OnTextChanged(EventArgs.Empty);
45 }
46
47
48 protected virtual void OnTextChanged(EventArgs e) {
49 if (TextChanged != null)
50 TextChanged(this,e);
51 }
52
53
54 protected override void Render(HtmlTextWriter output) {
55 output.Write("");
57 }
58 }
59}
60
我们详细说一下下面的两个方法:
第三个: GetPostBackClientHyperlink,该方法将由页面Page调用,用于产生客户端脚本,从超链接中引起回传,为了说明其执行回传功能,我们来创建军一个自定义控件(LinkButton_Demo),这个控件生成一个超链接,在点击链接时,将表单上传到服务器端.:
示例:
控件代码:
GetPostBackClientHyperlink 方法
1using System;
2using System.Data;
3using System.Configuration;
4using System.Web;
5using System.Web.Security;
6using System.Web.UI;
7using System.Web.UI.WebControls;
8using System.Web.UI.WebControls.WebParts;
9using System.Web.UI.HtmlControls;
10using System.ComponentModel;
11/**////
12/// GetPostBackClientHyperlink 用方法
13///
14///
15namespace cnblogs.sui
16{
17
18 [DefaultEvent("Click"),DefaultProperty("Text")]
19 public class LinkButton_demo : WebControl,IPostBackEventHandler
20 {
21 private static readonly object EventClick = new object();
22 [Bindable(true), Category("Behavior")]
23 public virtual string Text {
24
25 get {
26
27 string s = (string)ViewState["Text"];
28 return ((s == null) ? String.Empty : s);
29 }
30 set {
31
32 ViewState["Text"] = value;
33 }
34 }
35 protected override HtmlTextWriterTag TagKey
36 {
37 get
38 {
39 return HtmlTextWriterTag.A;
40 }
41 }
42 public event EventHandler Click {
43
44 add{
45 Events.AddHandler(EventClick, value);
46
47
48 }
49 remove {
50 Events.AddHandler(EventClick, value);
51 }
52 }
53 public void RaisePostBackEvent(string eventArgument) {
54 onClick(EventArgs.Empty);
55 }
56 protected override void AddAttributesToRender(HtmlTextWriter writer)
57 {
58
59 base.AddAttributesToRender(writer);
60 writer.AddAttribute(HtmlTextWriterAttribute.Href,Page.GetPostBackClientHyperlink(this,string.Empty));//注意这里
61
62 }
63 protected virtual void onClick(EventArgs e)
64 {
65
66 EventHandler clickHandler = (EventHandler)Events[EventClick];
67 if (clickHandler != null)
68 {
69 clickHandler(this, e);
70 }
71 }
72 protected override void Render(HtmlTextWriter writer)
73 {
74 if (Page != null)
75 {
76 Page.VerifyRenderingInServerForm(this);
77 }
78 base.Render(writer);
79 }
80 protected override void RenderContents(HtmlTextWriter writer)
81 {
82 writer.Write(Text);
83 //base.RenderContents(writer);
84 }
85 public LinkButton_demo()
86 {
87 //
88 // TOD 在此处添加构造函数逻辑
89 //
90 }
91 }
92}
Aspx页面:
1<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>
2<%@ Register Namespace="cnblogs.sui" TagPrefix="ss" %>
3
4
5
6
7 无标题页
8
16
17
18
23
24
25
结下来我们来分析其原理:
先看运行结果:
点击click me后,打出"send…."
当们查看其源代码,发现. 
我将看到由LinkButton_demo生成如下HTML语言。
click me
在页面底部,将看到两个隐藏域和一段javascript脚本.
现在分析一下是如何提供之些元素,我们重新来看看控件代码。我们在AddAttributes中有这么一段代码。将看到下面的调用:
Writer.AddAttribute(HtmlTextWriterAttribute.Href,Page.GetPostBackClientHyperlink(this,string.Empty));
GetPostBackClientHyperlink方法主要实现两个功能,
GetPostBackClientHyperlink返回一个字符串" javascript:__doPostBack('link','')",这个由页面生成到__doPostBack javascript函数的调用。参数值:以一个UniqueID和一个当控件生成多重回传元素时采用的可选字符串参数(我们将在下一个方法[GetCallbackEventReference]中来讲述)
GetPostBackClientHyperlink将告诉页面去生成两个隐藏域(__EVENTTARGET, __EVENTARGUMENT),以及引起回传(__doPostBack)的javascript函数,
当我们点了超链接后,发生了什么呢?
其实,当点击后,Javascript 函数__doPostBack被调用。这个函数把控件的UniqueID值给了__EVENTTARGET隐藏域中,把事件参数赋给了__EVENTARGUMENT隐藏域并回传表单,在服务器端,将读取过来的表单数据中的__EVENTTARGET变量,并调用控件的RaisePostBackEvent方法,此方法的UniqueID的值与__EVENTTARGET变量的值相匹配,此外,页面把表单发送数据中的__EVENTARGUMENT变量的值作为参数传给RaisePostBackEvent方法。不知道大家注意到一个细节没有,我们在这个LinkButton_demo控件中,没有给它附上UniqueID,而在我们那IPostBackEventHandler这个接口中举的那个例子,一定要用到name(id)给上一个UniqueID值,那是因为LinkButton_demo它会在HTML标签上自动生成作为name属性的UniqueID.
当我们生成的是一个表单元素不是超链接时,我们就要用到GetPostBackEventReference
第四个:GetPostBackEventReference
因为实现原理与GetPostBackClientHyperlink差不多,所以直接写个例子大家看看吧。
控件代码:
1using System;
2using System.Data;
3using System.Configuration;
4using System.Web;
5using System.Web.Security;
6using System.Web.UI;
7using System.Web.UI.WebControls;
8using System.Web.UI.WebControls.WebParts;
9using System.Web.UI.HtmlControls;
10using System.ComponentModel;
11/**////
12/// GetPostBackEventReference 的使用
13///
14///
15namespace cnblogs.suiqi
16{
17 [DefaultEvent("ClickN")]
18 [DefaultProperty("NextT")]
19
20 public class EventRef : WebControl,IPostBackEventHandler
21 {
22 private static readonly object EventClickN = new object();
23 private static readonly object EventClickP = new object();
24 [Bindable(true)]
25 public virtual string NextT {
26
27 get {
28
29 string s = (string)ViewState["NextT"];
30 return ((s == null) ? String.Empty : s);
31 }
32 set {
33 ViewState["NextT"] = value;
34 }
35 }
36 public virtual string PreviousT
37 {
38 get {
39
40 string s = (string)ViewState["PreviousT"];
41 return ((s == null) ? String.Empty : s);
42 }
43 set
44 {
45 ViewState["PreviousT"] = value;
46 }
47 }
48 public event EventHandler ClickN
49 {
50 add {
51 Events.AddHandler(EventClickN, value);
52 }
53
54 remove{
55 Events.AddHandler(EventClickN, value);
56 }
57 }
58 public event EventHandler ClickP
59 {
60 add
61 {
62 Events.AddHandler(EventClickP, value);
63 }
64
65 remove
66 {
67 Events.AddHandler(EventClickP, value);
68 }
69 }
70 protected virtual void onClickN(EventArgs e) {
71
72 EventHandler clickNextHandler = (EventHandler)Events[EventClickN];
73 if (clickNextHandler !=null)
74 {
75 clickNextHandler(this, e);
76 }
77 }
78 protected virtual void onClickP(EventArgs e)
79 {
80
81 EventHandler clickPreviousHandler = (EventHandler)Events[EventClickP];
82 if (clickPreviousHandler != null)
83 {
84 clickPreviousHandler(this, e);
85 }
86 }
87 public void RaisePostBackEvent(string eventArgument) {
88
89 if (eventArgument == "Previous")
90 {
91 onClickP(new EventArgs());
92 }
93 else if (eventArgument == "Next")
94 {
95 onClickN(EventArgs.Empty);
96 }
97
98 }
99 protected override void Render(HtmlTextWriter writer)
100 {
101 if (Page != null)
102 {
103 base.Page.VerifyRenderingInServerForm(this);
104 }
105 base.Render(writer);
106 }
107 protected override void AddAttributesToRender(HtmlTextWriter writer)
108 {
109 writer.AddAttribute(HtmlTextWriterAttribute.onclick, Page.GetPostBackEventReference(this, "Previous"));//注意这里,
110 writer.AddAttribute("language", "javascript");
111 writer.RenderBeginTag(HtmlTextWriterTag.Button);
112 writer.Write(this.PreviousT);
113 writer.RenderEndTag();
114 writer.AddAttribute(HtmlTextWriterAttribute.onclick, Page.GetPostBackEventReference(this, "Next"));//注意这里
115 writer.AddAttribute("language", "javascript");
116 writer.RenderBeginTag(HtmlTextWriterTag.Button);
117 writer.Write(this.NextT);
118 writer.RenderEndTag();
119
120
121 base.AddAttributesToRender(writer);
122 }
123 public EventRef()
124 {
125 //
126 // TOD 在此处添加构造函数逻辑
127 //
128 }
129 }
130}
示例代码:
1<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default3.aspx.cs" Inherits="Default3" %>
2<%@ Register Namespace="cnblogs.suiqi" TagPrefix="cn" %>
3
4
5
6
7 无标题页
8
19
20
21
27
28
29
最后我们看看生成后的html:
发现有如下代码:
其中的__doPostBack('eve','Previous'),这个就说明了第二个参数的作用,当控件生成多重回传元素时,采用的可选字符串参数