原文:ASP.NET自定义控件组件开发 第三章 为控件添加事件 后篇

第三章 为控件添加事件 后篇

前一篇文章只是简单的说了下事件,但是大家应该方法,在ASP.NET自定义控件中只是简单那么定义事件是行不

通。如果大家开发的是WinForm中的事件,之前的定义可能没有什么大的问题,只是在效率方法欠考虑而且,还是可以运行

的。

系列文章链接:

ASP.NET自定义控件组件开发 第一章 待续

ASP.NET自定义控件组件开发 第一章 第二篇 接着待续

ASP.NET自定义控件组件开发 第一章 第三篇

ASP.NET自定义控件组件开发 第二章 继承WebControl的自定义控件

ASP.NET自定义控件组件开发 第三章 为控件添加事件 前篇

ASP.NET自定义控件组件开发 第三章 为控件添加事件 后篇

ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl

ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl 后篇 --事件冒泡

ASP.NET自定义控件组件开发 第五章 模板控件开发

ASP.NET2.0自定义控件组件开发 第六章 深入讲解控件的属性

ASP.NET2.0组件控件开发视频 初体验

下面我们就回到ASP.NET中的事件。

大家也许看了我们之前定义的事件,确实,事件一般是那么定义的,但是那样定义事件后的,运行起来的效率不搞,

因为那样定义事件后,编译器在编译事件代码的时候,会自动的为我们加入很多多线程安全的代码,就是说,虽然我们只是

定义几行代码,大但是编译器为我们做了很多额外的事情,当然,这样代码的运行的效率可想而知。

在很多的时候,我们自定义控件的事件不是需要考虑多线程安全等问题的,所我们就要改变代码,使其运行的更加好,

我们就采用下面的方法:显示的申明事件:

Code
 1  
 2 //其实其实一个辅助的变量,用来做Hashtable中的”键“
 3 private static object ValidateCreditCardFormKey = new object();
 4         public event ValidateCreditCardFormEventHandler ValidateCreditCardForm
 5         {
 6             add
 7             {
 8                 Events.AddHandler(ValidateCreditCardFormKey, value);
 9             }
             remove
             {
                 Events.RemoveHandler(ValidateCreditCardFormKey, value);
             }
         }
 
        
         protected void OnValidateCreditCardForm(ValidateCreditCardFormEventArgs args)
         {
             ValidateCreditCardFormEventHandler handler = Events[ValidateCreditCardFormKey]
                                                                         as ValidateCreditCardFormEventHandler;
             if (handler != null)
                 handler(this, args);
         }

注意:其实就我们之前定义的事件的代码而言,编译器在在编译我们的代码的时候,也是编译成了上面的形式而且还额外

的加上了一些安全的控制代码,这里,我们现在不要编译器生成,而是我们自己写出来,效率就高了。

还有就是:如果一个事件在事件列表(是一个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
  protected override string SubmitButtonName
         {
             get
             {
                 return this.UniqueID ;
             }
         }

还有,每一次页面提交给服务器后,解析页面的this.UniqueID都不一样。而且,如果在页面中同时有两个CreditCardForm,我们也要保证两个控件的其他控件,如输入框等等的name也不一样,所以要分别重写name。

Code
 1 protected override string PaymentMethodListName
 2         {
 3             get
 4             {
 5                 return this.UniqueID + ":PaymentMethod";
 6             }
 7         }
 8 
 9         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接口,其实只有一个方法。而且也很简单,代码:

Code
 1  
 2 
 3 //大家看看我们只是将之前的事件通知代码移到了这里。
 4 void IPostBackEventHandler.RaisePostBackEvent(string args)
 5         {
 6             ValidateCreditCardFormEventArgs ve = new ValidateCreditCardFormEventArgs(
 7                 PaymentMethodText, CreditCardNoText, CardholderNameText, ExpirationDateText);
 8 
 9             OnValidateCreditCardForm(ve);
         }

这样以后,我们的控件就可以引发服务器回传了,即,当你点击“提交”按钮时,我们的浏览器的状态栏下面就有刷新的

进度条了。

注意,还有一个问题啊,我们确实能够使得我们的控件向服务器提交信息,但是服务器怎么来得到我们的提交的信息

呢?

并不是我们把信息向服务器提交后,就什么都不管了,然后服务器就”很听话的“进行验证。不是这样的,起码我们还要

告诉服务器,我们提交了哪些要被验证的信息。

那么服务器这样接受到我们的信息,,很简单,只要实现一个接口就可以了--IPostBackDataHandler。

接口有两个方法,第一个就是LoadPostData方法,就是来获取我们的信息,并且判断我们这次提交的信息和上次有变化

没有。

上面的方法返回一个布尔的值,如果返回true,就自动的调用下一个方法RaisePostDataChangedEvent,

大家可以根据方法的英文看到他们的作用。

这里我们只是讲下LoadPostData方法,方法的完成写法是这样的:

Code
 bool LoadPostData(string postDataKey, NameValueCollection values)
 {
 
 }

看见方法不要害怕,方法的参数,前一个参数,我们不要管,只要看看后面的参数就可以了。

我们的信息的提交,都是在相应的输入框,下拉框中写好了,传给服务器的,其实是以:键值对,传了的.

键:就是我们输入框等的名字,name

值:就是输入的值。

其实NameValueCollection就是一个哈希表,来存放键值对的。

我们之前的所有输入的信息被包含成了一个NameValueCollection传到服务器,然后服务器就通过对应的“键”(name)来获取值,然后验证。

代码如下:

Code
 1  bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection values)
 2         {
 3             string paymentMethod = values[PaymentMethodListName] == "" ? "Master" : "Visa";
 4             if (paymentMethod != PaymentMethodText)
 5             {
 6                 PaymentMethod = paymentMethod;
 7                 hasPaymentMethodChanged = true;
 8             }
 9 
             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,);
             if(expirationDate !=ExpirationDateText )
             {
                 ExpirationDateText =expirationDate ;
                 hasExpirationDateChanged =true ;
             }
 
 
             if(!string.IsNullOrEmpty (values [SubmitButtonName ]))
                 Page.RegisterRequiresRaiseEvent (this);
 
             return hasExpirationDateChanged||
                 hasCreditCardNoChanged ||
                 hasPaymentMethodChanged ||
                 hasCardholderNameChanged ;
 
         }

这样,我们整个控件就写完了,不知道大家懂了没:有问题回复!完整代码如下:

Code
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Text;
  4 using System.Web;
  5 using System.Web.UI;
  6 using System.Web.UI.WebControls;
  7 using System.Collections ;
  8 
  9 using System.Collections.Specialized ;
 10 
 11 namespace CreditCardForm
 12 {
 13     public class CreditCardForm6:CreditCardForm5 ,IPostBackEventHandler,IPostBackDataHandler
 14     {
 15         #region override name
 16         protected override string PaymentMethodListName
 17         {
 18             get
 19             {
 20                 return this.UniqueID + ":PaymentMethod";
 21             }
 22         }
 23 
 24         protected override string CreditCardNoTextName
 25         {
 26             get
 27             {
 28                 return this.UniqueID + ":CreditCardNo";
 29             }
 30         }
 31 
 32         protected override string CardholderNameTextName
 33         {
 34             get
 35             {
 36                 return this.UniqueID + ":CardholderName";
 37             }
 38         }
 39 
 40         protected override string MonthListName
 41         {
 42             get
 43             {
 44                 return this.UniqueID +":Month";
 45             }
 46         }
 47 
 48         protected override string YearListName
 49         {
 50             get
 51             {
 52                 return this.UniqueID + ":Year";
 53             }
 54         }
 55 
 56         protected override string SubmitButtonName
 57         {
 58             get
 59             {
 60                 return this.UniqueID ;
 61             }
 62         }
 63         #endregion
 64         #region prorerty
 65 
 66         public string PaymentMethodText
 67         {
 68             get
 69             {
 70                 return ViewState["PaymentMethod"] != null ? (string)ViewState["PaymentMethod"] : string.Empty ;
 71             }
 72             set
 73             {
 74                 ViewState["PaymentMethod"] = value;
 75             }
 76         }
 77 
 78 
 79         public string CreditCardNoText
 80         {
 81             get
 82             {
 83                 return ViewState["CreditCardNo"] != null ? (string)ViewState["CreditCardNo"] : string.Empty;
 84             }
 85             set
 86             {
 87                 ViewState["CreditCardNo"] = value;
 88             }
 89         }
 90 
 91         public string CardholderNameText
 92         {
 93             get
 94             {
 95                 return ViewState["CardholderName"] != null ? (string)ViewState["CardholderName"] : string.Empty;
 96             }
 97             set
 98             {
 99                 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 hasExpirationDateChanged;
 
         bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection values)
         {
             string paymentMethod = values[PaymentMethodListName] == "" ? "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,);
             if(expirationDate !=ExpirationDateText )
             {
                 ExpirationDateText =expirationDate ;
                 hasExpirationDateChanged =true ;
             }
 
 
             if(!string.IsNullOrEmpty (values [SubmitButtonName ]))
                 Page.RegisterRequiresRaiseEvent (this);
 
             return hasExpirationDateChanged||
                 hasCreditCardNoChanged ||
                 hasPaymentMethodChanged ||
                 hasCardholderNameChanged ;
 
         }
 
         void IPostBackDataHandler.RaisePostDataChangedEvent()
         {
             bool hasChanged;
             hasChanged = hasCardholderNameChanged ||
                 hasCreditCardNoChanged ||
                 hasPaymentMethodChanged ||
                 hasExpirationDateChanged;
 
             if (hasChanged)
             {
 
                 ValidateCreditCardFormEventArgs args = new ValidateCreditCardFormEventArgs(
                     PaymentMethod, CreditCardNoText, CardholderNameText, ExpirationDateText);
 
                 OnValidateCreditCardForm(args);
             }
         }
 
     }
 }
 

ASP.NET自定义控件组件开发 第三章 为控件添加事件 后篇的更多相关文章

  1. ASP.NET自定义控件组件开发 第三章 为控件添加事件 前篇

    原文:ASP.NET自定义控件组件开发 第三章 为控件添加事件 前篇 第三章 为控件添加事件 好了,我们之前以前开发一个控件.而且也添加了属性,开发也很规范,但是那个控件还差最后一点:添加事件. 系列 ...

  2. ASP.NET自定义控件组件开发 第五章 模板控件开发

    原文:ASP.NET自定义控件组件开发 第五章 模板控件开发 第五章 模板控件开发 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接 ...

  3. ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl

    原文:ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl 第四章 组合控件开发CompositeControl 大家好,今天我们来实现一个自定义的控件,之前我们已经 ...

  4. ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl 后篇 --事件冒泡

    原文:ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl 后篇 --事件冒泡 CompositeControl  后篇 --事件冒泡 系列文章链接: ASP.NET ...

  5. ASP.NET自定义控件组件开发 第一章 第三篇

    原文:ASP.NET自定义控件组件开发 第一章 第三篇 第三篇:第一章的完结篇 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接着待 ...

  6. ASP.NET自定义控件组件开发 第一章 第三篇 第一章的完结篇

    ASP.NET自定义控件组件开发 第一章 第三篇   第三篇:第一章的完结篇 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接着待续 ...

  7. ASP.NET2.0自定义控件组件开发 第六章 深入讲解控件的属性

    原文:ASP.NET2.0自定义控件组件开发 第六章 深入讲解控件的属性 深入讲解控件的属性持久化(一) 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开 ...

  8. ASP.NET自定义控件组件开发 第二章 继承WebControl的自定义控件

    原文:ASP.NET自定义控件组件开发 第二章 继承WebControl的自定义控件 第二章 继承于WebControl的自定义控件 到现在为止,我已经写了三篇关于自定义控件开发的文章,很感谢大家的支 ...

  9. ASP.NET自定义控件组件开发 第一章 第二篇 接着待续

    原文:ASP.NET自定义控件组件开发 第一章 第二篇 接着待续 ASP.NET自定义控件组件开发 第一章 第二篇 接着待续 很感谢大家给我的第一篇ASP.NET控件开发的支持!在写这些之前,我也看了 ...

随机推荐

  1. SVN Error: “' 'x' isn't in the same repository as 'y' ” during merge (并不在同一个版本库中)

    在使用svn merge命令报错 英文版本:SVN Error: “' 'x' isn't in the same repository as 'y' ” during merge 中文版本报错:并不 ...

  2. SE 2014年5月9日

    两企业接入到 Internet(A公司和B公司),企业内部的用户及服务器均能够访问到 Internet. 2. A公司规模较大,采用了接入层/汇聚层/核心层的划分模式,接入层划分了多vLan(如图), ...

  3. 强势围观,CSDN代码引用bug

    看我写的一篇blog  http://blog.csdn.net/laijieyao/article/details/41014355,在代码上引用了微软雅黑的字体,结果代码显示出来把我给惊呆了 竟然 ...

  4. java反射中Method类invoke方法的使用方法

    package com.zsw.test; import java.lang.reflect.Method;import java.lang.reflect.InvocationTargetExcep ...

  5. PyUnit框架学习

    http://www.oschina.net/question/12_27127#INSTALL http://www.360doc.com/content/11/0606/23/54470_1221 ...

  6. 在Amazon AWS RHEL 7上安装 配置PPTP VPN

    0 前言 0.1 为什么需要VPN? 国内的VPN不是必须,但是国外的VPN是很有用的.连接到国外的VPN服务器之后就可以访问Google,Facebook, Youtube等网站,没有Google的 ...

  7. 转载ECTouch1.0 修改后台广告管理中广告列表显示广告图片

    http://www.ectouch.cn/topics/94.html 效果 操作: 1. 修改后台控制器文件 调用出相关字段信息. mobile\include\apps\admin\contro ...

  8. Array of Objects

    You should be comfortable with the content in the modules up to and including the module "Array ...

  9. linux sed命令详解(转)

    简介 sed 是一种在线编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的 ...

  10. 找出二叉树中和为n的路径

    题目描述: 输入一个整数和一棵二元树.从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径.打印出和 与输入整数相等的所有路径. 二叉树中的路径 从二叉树的根节点出发,至二叉树的叶子节点的 ...