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

{
6
public event EventHandler Click; // 声明事件, 格式:修饰符+event+该事件的委托+事件命名,event的位置不可调换
7
}
8
public 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
4
using System;
5
namespace 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
53
namespace 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);