好了,言规正传,首先我们来说说委托和事件。

首先我们来看一个通俗的理解。
比如说一个公司(场景),你是老板,手下有两个员工,小张和小王。
你命令小王,如果小张玩游戏,则小王扣去小张500元钱。

这就是现实中的委托。

实际上,在写程序中,程序员就是老板,小张和小王就是两个对象。小张玩游戏是一个方法,小张还有一个游戏事件,他玩游戏激发这个事件。而小王就是事件处理对象,他负责把小张的钱扣除500。

所以,委托有如下几个要素:
1 激发事件的对象--就是小张
2 处理对象事件的对象--就是小王
3 定义委托,就是你让小王监视小张。

实际上,委托用来保存一个方法的引用。委托是一个类,当你对它实例化时,要提供一个引用函数,将其作为它构造函数的参数。 委托的声明如下:
public delegate void MyEventHanlder(object sender,EventArgs e)
这是,所谓的委托签名实际上指的是object和EventArgs类型的形参。
看下面的函数:
private void MyFunction(object sender,EventArgs e){...}
你可以将这个方法传递给委托的构造函数,如下:
MyEventHanlder eh=new MyEventHanlder (MyFunction);
这句话表达的含义是:如果你调用了eh,你就调用了MyFunction。

现在我们再来看事件:
事件是委托类型的变量。意思是:如果给事件命名,用event关键字和要使用的委托类型申明它即可,如下所示:
public event MyEventHanlder click;
现在我们还没有还没有实际引发这个事件,看下面的代码:

 
using System;
 2
using System.Web.UI;
 
3
 4
namespace CustomComponents
 
5{
 
6    /**//// <summary>
 7    /// SuperButton1 的摘要说明。
 8    /// </summary>
 9    //public delegate void MyEventHandler(object sender,EventArgs e);
10
11    public class SuperButton1 : Control, IPostBackEventHandler
12    {
13        // 声明Click事件委托
14        public event EventHandler Click;
15
16        // 定义OnClick事件处理程序
17        protected virtual void OnClick(EventArgs e)
18        {
19            if (Click != null)
20            {
21                Click(this, e);
22            }

23        }

24
25        // 实现RaisePostBackEvent方法,处理回发事件
26        public void RaisePostBackEvent(string eventArgument)
27        {
28            OnClick(EventArgs.Empty);
29        }

30
31        protected override void Render(HtmlTextWriter output)
32        {
33            output.Write("<INPUT TYPE=submit name=" + this.UniqueID +
34                " Value='确定' />");
35        }

36    }

37
38}

39

以上代码,有以下几点要弄清楚原因:
1.如果有自定义的委托,则一定要在类外定义,因为所有的类(包括在webform.aspx)页面中都需调用。如以上已被注释的代码:public delegate void MyEventHandler(object sender,EventArgs e);

2.if (Click != null)
   {
    Click(this, e);
   }
   可以调用所有注册方法,换句话理解,如果在页面上调用使用此控件时,需要首先注册方法,如下:
this.SuperButton11.Click1+= new System.EventHandler(this.SuperButton11_Click);否则会提示错误。

 3.为什么要在OnClick方法前加上protected virtual修辞符。
    关键字protected限定了 只有从该类继承的类才能调用该类中的所有方法。
  关键字virtual 表明了 在继承类中可以重写该方法。
     这两点非常有用,假设你在写一个从SuperButton1继承而来的类,通过重写OnClick方法,你可以在事件触发之前,进行一次其他的工作。 
protected override void OnClick(NumberReachedEventArgs e)
{
 base.OnClick(e);
}
注意:如果你没有调用base.OnClick(e), 那么从不会触发这个事件!在你继承该类而想剔出它的一些其他事件时,使用该方式是非常有用的。

4.还要注意我们用的是+= 而不是=;这是因为委托是特殊的对象,它可以引用多个对象(在这里是指它可以引用多个函数)。如下代码:
this.SuperButton11.Click1+= new System.EventHandler(this.SuperButton11_Click);
this.SuperButton11.Click1+= new System.EventHandler(this.SuperButton12_Click);

5.优化事件:
  原因:1.假设你在页面上多次使用这个控件,编译器将为每个事件委托实例生成一个字段。如果事件的数目很大,则一个委托一个字段的存储成本可能无法接受。.所以推荐采用另外一种优化的事件实现。
        2.另外,在Onclick方法的实现过程中,当用一个事件属性时,必须从EventHandlerList中取回委托,并转换成EventHandler类型。
相关代码表示如下:


 1using System;
 2
using System.Web.UI;
 
3
 4
namespace CustomComponents
 
5{
 
6    /**//// <summary>
 7    /// SuperButton1 的摘要说明。
 8    /// </summary>
 9    //public delegate void MyEventHandler(object sender,EventArgs e);
10
11    public class SuperButton1 : Control, IPostBackEventHandler
12    {
13        // 声明Click事件委托
14        private static readonly object ClickKey = new object();
15
16        public event EventHandler Click
17        {
18            add
19            {
20                Events.AddHandler(ClickKey, value);
21            }

22            remove
23            {
24                Events.RemoveHandler(ClickKey, value);
25            }

26        }

27
28
29        // 定义OnClick事件处理程序
30        protected virtual void OnClick(EventArgs e)
31        {
32            EventHandler Click =(EventHandler)Events[ClickKey];
33            if (Click != null)
34            {
35                Click(this, e);
36            }

37        }

38
39        // 实现RaisePostBackEvent方法,处理回发事件
40        public void RaisePostBackEvent(string eventArgument)
41        {
42            OnClick(EventArgs.Empty);
43        }

44
45        protected override void Render(HtmlTextWriter output)
46        {
47            output.Write("<INPUT TYPE=submit name=" + this.UniqueID +
48                " Value='确定' />");
49        }

50    }

51
52}





 

posted on 2006-09-14 21:26  jasonM  阅读(395)  评论(0编辑  收藏  举报