第三章 为控件添加事件 后篇
前一篇文章只是简单的说了下事件,但是大家应该方法,在自定义控件中只是简单那么定义事件是行不
通。如果大家开发的是WinForm中的事件,之前的定义可能没有什么大的问题,只是在效率方法欠考虑而且,还是可以运行
的。
系列文章链接:
自定义控件组件开发 第一章 待续
自定义控件组件开发 第一章 第二篇 接着待续
自定义控件组件开发 第一章 第三篇
自定义控件组件开发 第二章 继承WebControl的自定义控件
自定义控件组件开发 第三章 为控件添加事件 前篇
自定义控件组件开发 第三章 为控件添加事件 后篇
自定义控件组件开发 第四章 组合控件开发CompositeControl
自定义控件组件开发 第四章 组合控件开发CompositeControl 后篇 --事件冒泡
自定义控件组件开发 第五章 模板控件开发
2.0自定义控件组件开发 第六章 深入讲解控件的属性
2.0组件控件开发视频 初体验
下面我们就回到中的事件。
大家也许看了我们之前定义的事件,确实,事件一般是那么定义的,但是那样定义事件后的,运行起来的效率不搞,
因为那样定义事件后,编译器在编译事件代码的时候,会自动的为我们加入很多多线程安全的代码,就是说,虽然我们只是
定义几行代码,大但是编译器为我们做了很多额外的事情,当然,这样代码的运行的效率可想而知。
在很多的时候,我们自定义控件的事件不是需要考虑多线程安全等问题的,所我们就要改变代码,使其运行的更加好,
我们就采用下面的方法:显示的申明事件:
Code
1
2//其实其实一个辅助的变量,用来做Hashtable中的”键“
3privatestaticobjectValidateCreditCardFormKey=newobject();
4publiceventValidateCreditCardFormEventHandlerValidateCreditCardForm
5{
6add
7{
8Events.AddHandler(ValidateCreditCardFormKey,value);
9}
10remove
11{
12Events.RemoveHandler(ValidateCreditCardFormKey,value);
13}
14}
15
16
17protectedvoidOnValidateCreditCardForm(ValidateCreditCardFormEventArgsargs)
18{
19ValidateCreditCardFormEventHandlerhandler=Events[ValidateCreditCardFormKey]
20asValidateCreditCardFormEventHandler;
21if(handler!=null)
22handler(this,args);
23}
注意:其实就我们之前定义的事件的代码而言,编译器在在编译我们的代码的时候,也是编译成了上面的形式而且还额外
的加上了一些安全的控制代码,这里,我们现在不要编译器生成,而是我们自己写出来,效率就高了。
还有就是:如果一个事件在事件列表(是一个hashtable)已经注册了,当页面上有两个相同我们自定义控件,我的控件
的事件也只是在注册一次,效率也高了。
到这里一个事件就定义好了。
现在做的事情就是要触发事件。即,点击“提交”按钮,就触发。
我们先了理解一下流程:
点击“提交”,整个页面就向服务器提交了,之后就开始了页面的生命周期。
1.对页面进行解析,将原来页面中的源,如<asp:....></asp>这样的标记解析成相应的html代码,当
把页面解析完之后,页面在服务器就是html的样式了。(我这里说的很粗略,没有必要说的那么详细)。
2.解析后的页面就开始检查,刚才是哪个控件引发的服务器回传,即,是点击了哪个按钮后,整个页面向服
务器提交的,我们这里就是那个“提交”按钮。
3.解析后的页面检查“提交”按钮的name是否和控件(CreditCardForm)的name相同,如果相同。再检
查控件 CreditCardForm实现了IPostBackEventHandler接口,如果实现了,就引发我们之前定义的事件。
这样,我们的控件就和真正的服务器控件没有两样了。
(注意:上面的第3点:我们要按钮的name和CreditCardForm的name一样,这里的name我们无法用自己手动来设置他们
的一样,因为CreditCardForm的名字是有页面来设置的,页面将其设置为:this.UniqueID,所以我们只能将按钮的名字设置
为this.UniqueID,这样就可以了),所以我们要重写CreditCardForm5的一些属性:
Code
1protectedoverridestringSubmitButtonName
2{
3get
4{
5returnthis.UniqueID;
6}
7}
还有,每一次页面提交给服务器后,解析页面的this.UniqueID都不一样。而且,如果在页面中同时有两个CreditCardForm,我们也要保证两个控件的其他控件,如输入框等等的name也不一样,所以要分别重写name。
Code
1protectedoverridestringPaymentMethodListName
2{
3get
4{
5returnthis.UniqueID+":PaymentMethod";
6}
7}
8
9protectedoverridestringCreditCardNoTextName
10{
11get
12{
13returnthis.UniqueID+":CreditCardNo";
14}
15}
16
17protectedoverridestringCardholderNameTextName
18{
19get
20{
21returnthis.UniqueID+":CardholderName";
22}
23}
24
25protectedoverridestringMonthListName
26{
27get
28{
29returnthis.UniqueID+":Month";
30}
31}
32
33protectedoverridestringYearListName
34{
35get
36{
37returnthis.UniqueID+":Year";
38}
39}
这里以后,下面我们就只要实现IPostBackEventHandler接口,就可以调用我们的事件了,实现IPostBackEventHandler接口,其实只有一个方法。而且也很简单,代码:
Code
1
2
3//大家看看我们只是将之前的事件通知代码移到了这里。
4voidIPostBackEventHandler.RaisePostBackEvent(stringargs)
5{
6ValidateCreditCardFormEventArgsve=newValidateCreditCardFormEventArgs(
7PaymentMethodText,CreditCardNoText,CardholderNameText,ExpirationDateText);
8
9OnValidateCreditCardForm(ve);
10}
这样以后,我们的控件就可以引发服务器回传了,即,当你点击“提交”按钮时,我们的浏览器的状态栏下面就有刷新的
进度条了。
注意,还有一个问题啊,我们确实能够使得我们的控件向服务器提交信息,但是服务器怎么来得到我们的提交的信息
呢?
并不是我们把信息向服务器提交后,就什么都不管了,然后服务器就”很听话的“进行验证。不是这样的,起码我们还要
告诉服务器,我们提交了哪些要被验证的信息。
那么服务器这样接受到我们的信息,,很简单,只要实现一个接口就可以了--IPostBackDataHandler。
接口有两个方法,第一个就是LoadPostData方法,就是来获取我们的信息,并且判断我们这次提交的信息和上次有变化
没有。
上面的方法返回一个布尔的值,如果返回true,就自动的调用下一个方法RaisePostDataChangedEvent,
大家可以根据方法的英文看到他们的作用。
这里我们只是讲下LoadPostData方法,方法的完成写法是这样的:
Code
1boolLoadPostData(stringpostDataKey,NameValueCollectionvalues)
2{
3
4}
看见方法不要害怕,方法的参数,前一个参数,我们不要管,只要看看后面的参数就可以了。
我们的信息的提交,都是在相应的输入框,下拉框中写好了,传给服务器的,其实是以:键值对,传了的.
键:就是我们输入框等的名字,name
值:就是输入的值。
其实NameValueCollection就是一个哈希表,来存放键值对的。
我们之前的所有输入的信息被包含成了一个NameValueCollection传到服务器,然后服务器就通过对应的“键”(name)来获取值,然后验证。
代码如下:
Code
1boolIPostBackDataHandler.LoadPostData(stringpostDataKey,NameValueCollectionvalues)
2{
3stringpaymentMethod=values[PaymentMethodListName]=="0"?"Master":"Visa";
4if(paymentMethod!=PaymentMethodText)
5{
6PaymentMethod=paymentMethod;
7hasPaymentMethodChanged=true;
8}
9
10stringcreditCardNo=values[CreditCardNoTextName];
11if(creditCardNo!=CreditCardNoText)
12{
13CreditCardNoText=creditCardNo;
14hasCreditCardNoChanged=true;
15}
16
17stringcardholderName=values[CardholderNameTextName];
18if(cardholderName!=CardholderNameText)
19{
20CardholderNameText=cardholderName;
21hasCardholderNameChanged=true;
22}
23
24intmonth=int.Parse(values[MonthListName]);
25intyear=int.Parse(values[YearListName]);
26DateTimeexpirationDate=newDateTime(year,month,10);
27if(expirationDate!=ExpirationDateText)
28{
29ExpirationDateText=expirationDate;
30hasExpirationDateChanged=true;
31}
32
33
34if(!string.IsNullOrEmpty(values[SubmitButtonName]))
35Page.RegisterRequiresRaiseEvent(this);
36
37returnhasExpirationDateChanged||
38hasCreditCardNoChanged||
39hasPaymentMethodChanged||
40hasCardholderNameChanged;
41
42}
这样,我们整个控件就写完了,不知道大家懂了没:有问题回复!完整代码如下:
Code
1usingSystem;
2usingSystem.Collections.Generic;
3usingSystem.Text;
4usingSystem.Web;
5usingSystem.Web.UI;
6usingSystem.Web.UI.WebControls;
7usingSystem.Collections;
8
9usingSystem.Collections.Specialized;
10
11namespaceCreditCardForm
12{
13publicclassCreditCardForm6:CreditCardForm5,IPostBackEventHandler,IPostBackDataHandler
14{
15#regionoverridename
16protectedoverridestringPaymentMethodListName
17{
18get
19{
20returnthis.UniqueID+":PaymentMethod";
21}
22}
23
24protectedoverridestringCreditCardNoTextName
25{
26get
27{
28returnthis.UniqueID+":CreditCardNo";
29}
30}
31
32protectedoverridestringCardholderNameTextName
33{
34get
35{
36returnthis.UniqueID+":CardholderName";
37}
38}
39
40protectedoverridestringMonthListName
41{
42get
43{
44returnthis.UniqueID+":Month";
45}
46}
47
48protectedoverridestringYearListName
49{
50get
51{
52returnthis.UniqueID+":Year";
53}
54}
55
56protectedoverridestringSubmitButtonName
57{
58get
59{
60returnthis.UniqueID;
61}
62}
63#endregion
64#regionprorerty
65
66publicstringPaymentMethodText
67{
68get
69{
70returnViewState["PaymentMethod"]!=null?(string)ViewState["PaymentMethod"]:string.Empty;
71}
72set
73{
74ViewState["PaymentMethod"]=value;
75}
76}
77
78
79publicstringCreditCardNoText
80{
81get
82{
83returnViewState["CreditCardNo"]!=null?(string)ViewState["CreditCardNo"]:string.Empty;
84}
85set
86{
87ViewState["CreditCardNo"]=value;
88}
89}
90
91publicstringCardholderNameText
92{
93get
94{
95returnViewState["CardholderName"]!=null?(string)ViewState["CardholderName"]:string.Empty;
96}
97set
98{
99ViewState["CardholderName"]=value;
100}
101}
102
103publicDateTimeExpirationDateText
104{
105get
106{
107returnViewState["ExpirationDate"]!=null?(DateTime)ViewState["ExpirationDate"]:DateTime.Now;
108}
109set
110{
111ViewState["ExpirationDate"]=value;
112}
113}
114
115
116#endregion
117
118#regionevents
119privatestaticobjectValidateCreditCardFormKey=newobject();
120publiceventValidateCreditCardFormEventHandlerValidateCreditCardForm
121{
122add
123{
124Events.AddHandler(ValidateCreditCardFormKey,value);
125}
126remove
127{
128Events.RemoveHandler(ValidateCreditCardFormKey,value);
129}
130}
131
132
133protectedvoidOnValidateCreditCardForm(ValidateCreditCardFormEventArgsargs)
134{
135ValidateCreditCardFormEventHandlerhandler=Events[ValidateCreditCardFormKey]
136asValidateCreditCardFormEventHandler;
137if(handler!=null)
138handler(this,args);
139}
140
141#endregion
142voidIPostBackEventHandler.RaisePostBackEvent(stringargs)
143{
144ValidateCreditCardFormEventArgsve=newValidateCreditCardFormEventArgs(
145PaymentMethodText,CreditCardNoText,CardholderNameText,ExpirationDateText);
146
147OnValidateCreditCardForm(ve);
148}
149
150privateboolhasPaymentMethodChanged;
151privateboolhasCreditCardNoChanged;
152privateboolhasCardholderNameChanged;
153privateboolhasExpirationDateChanged;
154
155boolIPostBackDataHandler.LoadPostData(stringpostDataKey,NameValueCollectionvalues)
156{
157stringpaymentMethod=values[PaymentMethodListName]=="0"?"Master":"Visa";
158if(paymentMethod!=PaymentMethodText)
159{
160PaymentMethod=paymentMethod;
161hasPaymentMethodChanged=true;
162}
163
164stringcreditCardNo=values[CreditCardNoTextName];
165if(creditCardNo!=CreditCardNoText)
166{
167CreditCardNoText=creditCardNo;
168hasCreditCardNoChanged=true;
169}
170
171stringcardholderName=values[CardholderNameTextName];
172if(cardholderName!=CardholderNameText)
173{
174CardholderNameText=cardholderName;
175hasCardholderNameChanged=true;
176}
177
178intmonth=int.Parse(values[MonthListName]);
179intyear=int.Parse(values[YearListName]);
180DateTimeexpirationDate=newDateTime(year,month,10);
181if(expirationDate!=ExpirationDateText)
182{
183ExpirationDateText=expirationDate;
184hasExpirationDateChanged=true;
185}
186
187
188if(!string.IsNullOrEmpty(values[SubmitButtonName]))
189Page.RegisterRequiresRaiseEvent(this);
190
191returnhasExpirationDateChanged||
192hasCreditCardNoChanged||
193hasPaymentMethodChanged||
194hasCardholderNameChanged;
195
196}
197
198voidIPostBackDataHandler.RaisePostDataChangedEvent()
199{
200boolhasChanged;
201hasChanged=hasCardholderNameChanged||
202hasCreditCardNoChanged||
203hasPaymentMethodChanged||
204hasExpirationDateChanged;
205
206if(hasChanged)
207{
208
209ValidateCreditCardFormEventArgsargs=newValidateCreditCardFormEventArgs(
210PaymentMethod,CreditCardNoText,CardholderNameText,ExpirationDateText);
211
212OnValidateCreditCardForm(args);
213}
214}
215
216}
217}
218