关于事件

事件是一种使对象或类能够提供通知的成员。客户端可以通过提供事件处理程序为相应的事件添加可执行代码。
下面这个代码显示如何将事件处理程序添加到 Button 类的实例:
 1// @马志远  Copyright
 2
 3public delegate void EventHandler(object sender, EventArgs e);    // 使用事件,首先声明事件对应的 委托.
 4public class Button : Control                                    // 继续一个Button控件
 5{
 6    public event EventHandler Click;        // 声明事件, 格式:修饰符+event+该事件的委托+事件命名,event的位置不可调换
 7}

 8public class LoginDialog : Form                // 窗体
 9{
10    Button OkButton;                        // 声明一个按钮的实例:OkButton
11    Button CancelButton;                    // 声明另一个按钮实例:CancelButton
12
13    public LoginDialog()                    // 一个Constructor
14    {
15        OkButton            = new Button();
16        OkButton.Click        +=new EventHandler(OkButton_Click);    // 加入事件 Click
17
18        CancelButton        = new Button();
19        CancelButton.Click    +=new EventHandler(CancelButton_Click);
20    }

21
22    void OkButton_Click(object sender, EventArgs e)                // 委托所对应的事件处理程序 OkButton_Click
23    {
24        // 写上OKButton.Click的事件程序
25    }

26
27    void CancelButton_Click(object sender, EventArgs e)            // 委托所对应的事件处理程序 CancelButton_Click
28    {
29        // 写上CancelButton_Click的事件处理程序.
30    }

31}

为了创建并使用 C# 事件,必须采取以下步骤:

  1. 创建或标识一个委托。如果正在定义自己的事件,还必须确保有与事件关键字一起使用的委托。如果已经预定义了事件(例如在 .NET Framework 中),则事件的使用者只需要知道委托的名称。
  2. 创建一个类,包含:
    1. 从委托创建的事件。
    2. (可选)验证用 event 关键字声明的委托实例是否存在的方法。否则,该逻辑必须放置在引发此事件的代码中。
    3. 调用此事件的方法。这些方法可以重写一些基类功能。

    此类定义事件。

  3. 定义一个或多个将方法连接到事件的类。所有这些类都包括:
    • 使用 += 运算符和 -= 运算符将一个或多个方法与基类中的事件关联。
    • 将与事件关联的方法的定义。
  4. 使用此事件
    • 创建包含事件声明的类对象。
    • 使用定义的构造函数,创建包含事件定义的类对象。

C# 中的“事件”是当对象发生某些有趣的事情时,类向该类的客户提供通知的一种方法。事件最常见的用途是用于图形用户界面;通常,表示界面中的控件的类具有一些事件,当用户对控件进行某些操作(如单击某个按钮)时,将通知这些事件。

但是事件未必只用于图形界面。事件为对象提供一种通常很有用的方法来发出信号表示状态更改,这些状态更改可能对该对象的客户很有用。事件是创建类的重要构造块,这些类可在大量的不同程序中重复使用。

使用委托来声明事件。事件是类允许客户为其提供方法(事件发生时应调用这些方法)的委托的一种方法。事件发生时,将调用其客户提供给它的委托。

生活中的使用事件:例如,某字处理器可能包含打开的文档的列表。每当该列表更改时,可能需要通知字处理器中的许多不同对象,以便能够更新用户界面。使用事件,维护文档列表的代码不需要知道需要通知谁,一旦文档列表发生了更改,将自动调用该事件,正确通知每个需要通知的对象。使用事件提高了程序的模块化程度。


  1//版权所有 (C) 2000 Microsoft Corporation。保留所有权利。
  2
  3// events1.cs
  4using System;
  5namespace MyCollections 
  6{
  7   using System.Collections;
  8
  9   // 用于与更改通知挂钩的委托类型。
 10   public delegate void ChangedEventHandler(object sender, EventArgs e);
 11
 12   // 一个类,该类与 ArrayList 类似,但每当列表更改时将发送
 13   // 事件通知。
 14   public class ListWithChangedEvent: ArrayList 
 15   {
 16      // 一个事件,每当列表元素更改时,客户端可以使用该事件
 17      // 来获得通知。
 18      public event ChangedEventHandler Changed;
 19
 20      // 调用 Changed 事件;每当列表更改时调用
 21      protected virtual void OnChanged(EventArgs e) 
 22      {
 23         if (Changed != null)
 24            Changed(this, e);
 25      }

 26
 27      // 重写可更改列表的某些方法;
 28      // 在重写每个方法后调用事件
 29      public override int Add(object value) 
 30      {
 31         int i = base.Add(value);
 32         OnChanged(EventArgs.Empty);
 33         return i;
 34      }

 35
 36      public override void Clear() 
 37      {
 38         base.Clear();
 39         OnChanged(EventArgs.Empty);
 40      }

 41
 42      public override object this[int index] 
 43      {
 44         set 
 45         {
 46            base[index] = value;
 47            OnChanged(EventArgs.Empty);
 48         }

 49      }

 50   }

 51}

 52
 53namespace TestEvents 
 54{
 55   using MyCollections;
 56
 57   class EventListener 
 58   {
 59      private ListWithChangedEvent List;
 60
 61      public EventListener(ListWithChangedEvent list) 
 62      {
 63         List = list;
 64         // 将“ListChanged”添加到“List”中的 Changed 事件。
 65         List.Changed += new ChangedEventHandler(ListChanged);
 66      }

 67
 68      // 这将在列表发生更改时调用。
 69      private void ListChanged(object sender, EventArgs e) 
 70      {
 71         Console.WriteLine("This is called when the event fires.");
 72      }

 73
 74      public void Detach() 
 75      {
 76         // 分离事件并删除列表
 77         List.Changed -= new ChangedEventHandler(ListChanged);
 78         List = null;
 79      }

 80   }

 81
 82   class Test 
 83   {
 84      // 测试 ListWithChangedEvent 类。
 85      public static void Main() 
 86      {
 87      // 创建新的列表。
 88      ListWithChangedEvent list = new ListWithChangedEvent();
 89
 90      // 创建侦听列表的更改事件的类。
 91      EventListener listener = new EventListener(list);
 92
 93      // 在列表中添加和移除项。
 94      list.Add("item 1");
 95      list.Clear();
 96      listener.Detach();
 97      }

 98   }

 99}

100

输出
This is called when the event fires.
This is called when the event fires.
代码讨论
声明事件
   若要在类内声明事件,首先必须声明该事件的委托类型(如果尚未声明的话)。
public delegate void ChangedEventHandler(object sender, EventArgs e);
委托类型定义传递给处理该事件的方法的一组参数。多个事件可共享相同的委托类型,因此仅当尚未声明任何合适的委托类型时才需要执行该步骤。
接下来,声明事件本身。
public event ChangedEventHandler Changed;
声明事件的方法与声明委托类型的字段类似,只是关键字 event 在事件声明前面,在修饰符后面。事件通常被声明为公共事件,但允许任意可访问修饰符。
调用事件   类声明了事件以后,可以就像处理所指示的委托类型的字段那样处理该事件。如果没有任何客户将委托与该事件挂钩,该字段将为空;否则该字段引用应在调用该事件时调用的委托。因此,调用事件时通常先检查是否为空,然后再调用事件。
if (Changed != null)
Changed(this, e);
调用事件只能从声明该事件的类内进行。
与事件挂钩   从声明事件的类外看,事件像个字段,但对该字段的访问是非常受限制的。只可进行如下操作:
在该字段上撰写新的委托。
从字段(可能是复合字段)移除委托。
使用 += 和 -= 运算符完成此操作。为开始接收事件调用,客户代码先创建事件类型的委托,该委托引用应从事件调用的方法。然后它使用 += 将该委托写到事件可能连接到的其他任何委托上。
// Add "ListChanged" to the Changed event on "List":
List.Changed += new ChangedEventHandler(ListChanged);
当客户代码完成接收事件调用后,它将使用运算符 -= 从事件移除其委托。
// Detach the event and delete the list:
List.Changed -= new ChangedEventHandler(ListChanged);
posted @ 2005-11-29 14:42    阅读(252)  评论(0编辑  收藏  举报