前一篇文章只是简单的说了下事件,但是大家应该方法,在ASP.NET自定义控件中只是简单那么定义事件是行不通。如果大家开发的是WinForm中的事件,之前的定义可能没有什么大的问题,只是在效率方法欠考虑而且,还是可以运行的。
下面我们就回到ASP.NET中的事件。
大家也许看了我们之前定义的事件,确实,事件一般是那么定义的,但是那样定义事件后的,运行起来的效率不搞,因为那样定义事件后,编译器在编译事件代码的时候,会自动的为我们加入很多多线程安全的代码,就是说,虽然我们只是定义几行代码,大但是编译器为我们做了很多额外的事情,当然,这样代码的运行的效率可想而知。
在很多的时候,我们自定义控件的事件不是需要考虑多线程安全等问题的,所我们就要改变代码,使其运行的更加好,我们就采用下面的方法:显示的申明事件:
- //其实其实一个辅助的变量,用来做Hashtable中的”键“
- private static object ValidateCreditCardFormKey = new object();
- public event ValidateCreditCardFormEventHandler ValidateCreditCardForm
- {
- add
- {
- Events.AddHandler(ValidateCreditCardFormKey, value);
- }
- remove
- {
- Events.RemoveHandler(ValidateCreditCardFormKey, value);
- }
- }
- protected void OnValidateCreditCardForm(ValidateCreditCardFormEventArgs args)
- {
- ValidateCreditCardFormEventHandler handler = Events[ValidateCreditCardFormKey]
- as ValidateCreditCardFormEventHandler;
- if (handler != null)
- handler(this, args);
- }
注意:其实就我们之前定义的事件的代码而言,编译器在在编译我们的代码的时候,也是编译成了上面的形式而且还额外的加上了一些安全的控制代码,这里,我们现在不要编译器生成,而是我们自己写出来,效率就高了。
还有就是:如果一个事件在事件列表(是一个hashtable)已经注册了,当页面上有两个相同我们自定义控件,控件的事件也只是在注册一次,效率也高了。
到这里一个事件就定义好了。
现在做的事情就是要触发事件。即,点击“提交”按钮,就触发。
我们先了理解一下流程:
点击“提交”,整个页面就向服务器提交了,之后就开始了页面的生命周期。
1.对页面进行解析,将原来页面中的源,如这样的标记解析成相应的html代码,当把页面解析完之后,页面在服务器就是html的样式了。(我这里说的很粗略,没有必要说的那么详细)。
2.解析后的页面就开始检查,刚才是哪个控件引发的服务器回传,即,是点击了哪个按钮后,整个页面向服务器提交的,我们这里就是那个“提交”按钮。
解析后的页面检查“提交”按钮的name是否和控件(CreditCardForm)的name相同,如果相同。再检查控件 CreditCardForm实现了IPostBackEventHandler接口,如果实现了,就引发我们之前定义的事件。
我们的控件就和真正的服务器控件没有两样了。
注意:上面的第3点:我们要按钮的name和CreditCardForm的name一样,这里的name我们无法用自己手动来设置他们的一样,因为CreditCardForm的名字是有页面来设置的,页面将其设置为:this.UniqueID,所以我们只能将按钮的名字设置为this.UniqueID,这样就可以了),所以我们要重写CreditCardForm5的一些属性:
- protected override string SubmitButtonName
- {
- get
- {
- return this.UniqueID;
- }
- }
还有,每一次页面提交给服务器后,解析页面的this.UniqueID都不一样。而且,如果在页面中同时有两个CreditCardForm,我们也要保证两个控件的其他控件,如输入框等等的name也不一样,所以要分别重写name。
- protected override string PaymentMethodListName
- {
- get
- {
- return this.UniqueID + ":PaymentMethod";
- }
- }
- protected override string CreditCardNoTextName
- {
- get
- {
- return this.UniqueID + ":CreditCardNo";
- }
- }
- protected override string CardholderNameTextName
- {
- get
- {
- return this.UniqueID + ":CardholderName";
- }
- }
- protected override string MonthListName
- {
- get
- {
- return this.UniqueID + ":Month";
- }
- }
- protected override string YearListName
- {
- get
- {
- return this.UniqueID + ":Year";
- }
- }
这里以后,下面我们就只要实现IPostBackEventHandler接口,就可以调用我们的事件了,实现IPostBackEventHandler接口,其实只有一个方法。而且也很简单,代码:
- //大家看看我们只是将之前的事件通知代码移到了这里。
- void IPostBackEventHandler.RaisePostBackEvent(string args)
- {
- ValidateCreditCardFormEventArgs ve = new ValidateCreditCardFormEventArgs(
- PaymentMethodText, CreditCardNoText, CardholderNameText, ExpirationDateText);
- OnValidateCreditCardForm(ve);
- }
这样以后,我们的控件就可以引发服务器回传了,即,当你点击“提交”按钮时,我们的浏览器的状态栏下面就有刷新的进度条了。
注意,还有一个问题啊,我们确实能够使得我们的控件向服务器提交信息,但是服务器怎么来得到我们的提交的信息呢?
并不是我们把信息向服务器提交后,就什么都不管了,然后服务器就”很听话的“进行验证。不是这样的,起码我们还要告诉服务器,我们提交了哪些要被验证的信息。
那么服务器这样接受到我们的信息,,很简单,只要实现一个接口就可以了--IPostBackDataHandler。
接口有两个方法,第一个就是LoadPostData方法,就是来获取我们的信息,并且判断我们这次提交的信息和上次有变化没有。
上面的方法返回一个布尔的值,如果返回true,就自动的调用下一个方法RaisePostDataChangedEvent,大家可以根据方法的英文看到他们的作用。
这里我们只是讲下LoadPostData方法,方法的完成写法是这样的:
- bool LoadPostData(string postDataKey, NameValueCollection values)
- {
-
- }
看见方法不要害怕,方法的参数,前一个参数,我们不要管,只要看看后面的参数就可以了。
我们的信息的提交,都是在相应的输入框,下拉框中写好了,传给服务器的,其实是以:键值对,传了的。
键:就是我们输入框等的名字,name
值:就是输入的值。
其实NameValueCollection就是一个哈希表,来存放键值对的。
我们之前的所有输入的信息被包含成了一个NameValueCollection传到服务器,然后服务器就通过对应的“键”(name)来获取值,然后验证。
代码如下:
- bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection values)
- {
- string paymentMethod = values[PaymentMethodListName] == "0" ? "Master" : "Visa";
- if (paymentMethod != PaymentMethodText)
- {
- PaymentMethod = paymentMethod;
- hasPaymentMethodChanged = true;
- }
- string creditCardNo = values[CreditCardNoTextName];
- if (creditCardNo != CreditCardNoText)
- {
- CreditCardNoText = creditCardNo;
- hasCreditCardNoChanged = true;
- }
- string cardholderName = values[CardholderNameTextName];
- if (cardholderName != CardholderNameText)
- {
- CardholderNameText = cardholderName;
- hasCardholderNameChanged = true;
- }
- int month = int.Parse(values[MonthListName]);
- int year = int.Parse(values[YearListName]);
- DateTime expirationDate = new DateTime(year, month, 10);
- if (expirationDate != ExpirationDateText)
- {
- ExpirationDateText = expirationDate;
- ha*** pirationDateChanged = true;
- }
- if (!string.IsNullOrEmpty(values[SubmitButtonName]))
- Page.RegisterRequiresRaiseEvent(this);
- return ha * **pirationDateChanged ||
- hasCreditCardNoChanged ||
- hasPaymentMethodChanged ||
- hasCardholderNameChanged;
- }
这样,我们整个控件就写完了,不知道大家懂了没:有问题回复!完整代码如下:
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Web;
- using System.Web.UI;
- using System.Web.UI.WebControls;
- using System.Collections ;
- using System.Collections.Specialized ;
- namespace CreditCardForm
- {
- public class CreditCardForm6:CreditCardForm5 ,IPostBackEventHandler,IPostBackDataHandler
- {
- #region override name
- protected override string PaymentMethodListName
- {
- get
- {
- return this.UniqueID + ":PaymentMethod";
- }
- }
- protected override string CreditCardNoTextName
- {
- get
- {
- return this.UniqueID + ":CreditCardNo";
- }
- }
- protected override string CardholderNameTextName
- {
- get
- {
- return this.UniqueID + ":CardholderName";
- }
- }
- protected override string MonthListName
- {
- get
- {
- return this.UniqueID +":Month";
- }
- }
- protected override string YearListName
- {
- get
- {
- return this.UniqueID + ":Year";
- }
- }
- protected override string SubmitButtonName
- {
- get
- {
- return this.UniqueID ;
- }
- }
- #endregion
- #region prorerty
- public string PaymentMethodText
- {
- get
- {
- return ViewState["PaymentMethod"] != null ? (string)ViewState["PaymentMethod"] : string.Empty ;
- }
- set
- {
- ViewState["PaymentMethod"] = value;
- }
- }
- public string CreditCardNoText
- {
- get
- {
- return ViewState["CreditCardNo"] != null ? (string)ViewState["CreditCardNo"] : string.Empty;
- }
- set
- {
- ViewState["CreditCardNo"] = value;
- }
- }
- public string CardholderNameText
- {
- get
- {
- return ViewState["CardholderName"] != null ? (string)ViewState["CardholderName"] : string.Empty;
- }
- set
- {
- ViewState["CardholderName"] = value;
- }
- }
- public DateTime ExpirationDateText
- {
- get
- {
- return ViewState["ExpirationDate"] != null ? (DateTime)ViewState["ExpirationDate"] : DateTime.Now;
- }
- set
- {
- ViewState["ExpirationDate"] = value;
- }
- }
- #endregion
- #region events
- private static object ValidateCreditCardFormKey = new object();
- public event ValidateCreditCardFormEventHandler ValidateCreditCardForm
- {
- add
- {
- Events.AddHandler(ValidateCreditCardFormKey, value);
- }
- remove
- {
- Events.RemoveHandler(ValidateCreditCardFormKey, value);
- }
- }
-
- protected void OnValidateCreditCardForm(ValidateCreditCardFormEventArgs args)
- {
- ValidateCreditCardFormEventHandler handler = Events[ValidateCreditCardFormKey]
- as ValidateCreditCardFormEventHandler;
- if (handler != null)
- handler(this, args);
- }
- #endregion
- void IPostBackEventHandler.RaisePostBackEvent(string args)
- {
- ValidateCreditCardFormEventArgs ve = new ValidateCreditCardFormEventArgs(
- PaymentMethodText, CreditCardNoText, CardholderNameText, ExpirationDateText);
- OnValidateCreditCardForm(ve);
- }
- private bool hasPaymentMethodChanged;
- private bool hasCreditCardNoChanged;
- private bool hasCardholderNameChanged;
- private bool ha***pirationDateChanged;
- bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection values)
- {
- string paymentMethod = values[PaymentMethodListName] == "0" ? "Master" : "Visa";
- if (paymentMethod != PaymentMethodText)
- {
- PaymentMethod = paymentMethod;
- hasPaymentMethodChanged = true;
- }
- string creditCardNo = values[CreditCardNoTextName];
- if (creditCardNo != CreditCardNoText)
- {
- CreditCardNoText = creditCardNo;
- hasCreditCardNoChanged = true;
- }
- string cardholderName = values[CardholderNameTextName];
- if (cardholderName != CardholderNameText)
- {
- CardholderNameText = cardholderName;
- hasCardholderNameChanged = true;
- }
- int month = int.Parse(values[MonthListName]);
- int year=int.Parse (values [YearListName ]);
- DateTime expirationDate=new DateTime (year ,month,10);
- if(expirationDate !=ExpirationDateText )
- {
- ExpirationDateText =expirationDate ;
- ha***pirationDateChanged =true ;
- }
- if(!string.IsNullOrEmpty (values [SubmitButtonName ]))
- Page.RegisterRequiresRaiseEvent (this);
- return ha***pirationDateChanged||
- hasCreditCardNoChanged ||
- hasPaymentMethodChanged ||
- hasCardholderNameChanged ;
- }
- void IPostBackDataHandler.RaisePostDataChangedEvent()
- {
- bool hasChanged;
- hasChanged = hasCardholderNameChanged ||
- hasCreditCardNoChanged ||
- hasPaymentMethodChanged ||
- ha***pirationDateChanged;
- if (hasChanged)
- {
- ValidateCreditCardFormEventArgs args = new ValidateCreditCardFormEventArgs(
- PaymentMethod, CreditCardNoText, CardholderNameText, ExpirationDateText);
- OnValidateCreditCardForm(args);
- }
- }
- }
- }