关于事件
事件是一种使对象或类能够提供通知的成员。客户端可以通过提供事件处理程序为相应的事件添加可执行代码。
下面这个代码显示如何将事件处理程序添加到
输出
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);
下面这个代码显示如何将事件处理程序添加到
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}
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# 事件,必须采取以下步骤:
- 创建或标识一个委托。如果正在定义自己的事件,还必须确保有与事件关键字一起使用的委托。如果已经预定义了事件(例如在 .NET Framework 中),则事件的使用者只需要知道委托的名称。
- 创建一个类,包含:
- 从委托创建的事件。
- (可选)验证用 event 关键字声明的委托实例是否存在的方法。否则,该逻辑必须放置在引发此事件的代码中。
- 调用此事件的方法。这些方法可以重写一些基类功能。
此类定义事件。
- 定义一个或多个将方法连接到事件的类。所有这些类都包括:
- 使用 += 运算符和 -= 运算符将一个或多个方法与基类中的事件关联。
- 将与事件关联的方法的定义。
- 使用此事件:
- 创建包含事件声明的类对象。
- 使用定义的构造函数,创建包含事件定义的类对象。
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
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);