事件是对象发送的消息,以发信号通知操作的发生。操作可能是由用户交互(例如鼠标单击)引起的,也可能是由某些其他的程序逻辑触发的。引发事件的对象称为事件发送方。捕获事件并对其作出响应的对象叫做事件接收方。
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
在事件通信中,事件发送方类不知道哪个对象或方法将接收到(处理)它引发的事件。所需要的是在源和接收方之间存在一个媒介(或类似指针的机制)。.NET Framework 定义了一个特殊的类型(Delegate),该类型提供函数指针的功能。
委托是可保存对方法的引用的类。与其他的类不同,委托类具有一个签名,并且它只能对与其签名匹配的方法进行引用。这样,委托就等效于一个类型安全函数指针或一个回调。虽然委托具有许多其他的用途,但这里只讨论委托的事件处理功能。一个委托声明足以定义一个委托类。声明提供委托的签名,公共语言运行库提供实现。下面的示例显示了事件委托声明。
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
只有当事件生成事件数据时才需要自定义事件委托。许多事件,包括一些用户界面事件(例如鼠标单击)在内,都不生成事件数据。在这种情况下,类库中为无数据事件提供的事件委托 System.EventHandler 便足够了。
下面的示例程序阐释如何在一个类中引发一个事件,然后在另一个类中处理该事件。AlarmClock 类定义公共事件 Alarm,并提供引发该事件的方法。AlarmEventArgs 类派生自 EventArgs,并定义 Alarm 事件特定的数据。WakeMeUp 类定义处理 Alarm 事件的 AlarmRang 方法。AlarmDriver 类一起使用类,将使用 WakeMeUp 的 AlarmRang 方法设置为处理 AlarmClock 的 Alarm 事件。
// EventSample.cs.
//
namespace EventSample
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
using System;
using System.ComponentModel;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// Class that contains the data for
// the alarm event. Derives from System.EventArgs.
// 包含警报事件数据的类,从System.EventArgs继承
public class AlarmEventArgs : EventArgs
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
private readonly bool snoozePressed;
private readonly int nrings;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// 构造函数.
//
public AlarmEventArgs(bool snoozePressed, int nrings)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.snoozePressed = snoozePressed;
this.nrings = nrings;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// The NumRings property returns the number of rings
// that the alarm clock has sounded when the alarm event
// is generated.
// 当闹铃事件发生时,闹钟响的次数
public int NumRings
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return nrings; }
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// The SnoozePressed property indicates whether the snooze
// button is pressed on the alarm when the alarm event is generated.
// 当闹铃事件发生时,闹钟的按钮被按下,就停止闹铃
public bool SnoozePressed
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return snoozePressed; }
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// The AlarmText property that contains the wake-up message.
// 唤醒语言
public string AlarmText
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (snoozePressed)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return ("Wake Up!!! Snooze time is over.");
}
else
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return ("Wake Up!");
}
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// Delegate declaration.
// 委托声明
public delegate void AlarmEventHandler(object sender, AlarmEventArgs e);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// The Alarm class that raises the alarm event.
// 产生闹钟事件的闹钟类
public class AlarmClock
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
private bool snoozePressed = false;
private int nrings = 0;
private bool stop = false;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// The Stop property indicates whether the
// alarm should be turned off.
// 停止属性说明闹钟是否被关闭
public bool Stop
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return stop; }
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ stop = value; }
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// The SnoozePressed property indicates whether the snooze
// button is pressed on the alarm when the alarm event is generated.
// SnoozePressed属性说明当闹铃时间发生时,snooze button 是否被按下
public bool SnoozePressed
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return snoozePressed; }
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ snoozePressed = value; }
}
// The event member that is of type AlarmEventHandler.
// AlarmEventHandler类型的事件成员
public event AlarmEventHandler Alarm;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// The protected OnAlarm method raises the event by invoking
// the delegates. The sender is always this, the current instance
// of the class.
// 受保护的OnAlarm方法通过激发委托产生事件。发生方就是当前的类事例。
protected virtual void OnAlarm(AlarmEventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (Alarm != null)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
// Invokes the delegates.
// 唤醒委托
Alarm(this, e);
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// This alarm clock does not have
// a user interface.
// To simulate the alarm mechanism it has a loop
// that raises the alarm event at every iteration
// with a time delay of 300 milliseconds,
// if snooze is not pressed. If snooze is pressed,
// the time delay is 1000 milliseconds.
// 闹铃没有用户接口。为了激发闹铃机制,采用循环机制模拟。
public void Start()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
for (; ; )
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
nrings++;
if (stop)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
break;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
else if (snoozePressed)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
System.Threading.Thread.Sleep(1000);
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
AlarmEventArgs e = new AlarmEventArgs(snoozePressed,
nrings);
OnAlarm(e);
}
}
else
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
System.Threading.Thread.Sleep(300);
AlarmEventArgs e = new AlarmEventArgs(snoozePressed,
nrings);
OnAlarm(e);
}
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// The WakeMeUp class has a method AlarmRang that handles the
// alarm event.
// WakeMeUp类的AlarmRang方法操作闹铃事件
public class WakeMeUp
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void AlarmRang(object sender, AlarmEventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Console.WriteLine(e.AlarmText + "\n");
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
if (!(e.SnoozePressed))
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (e.NumRings % 10 == 0)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.WriteLine(" Let alarm ring? Enter Y");
Console.WriteLine(" Press Snooze? Enter N");
Console.WriteLine(" Stop Alarm? Enter Q");
String input = Console.ReadLine();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
if (input.Equals("Y") || input.Equals("y")) return;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
else if (input.Equals("N") || input.Equals("n"))
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
((AlarmClock)sender).SnoozePressed = true;
return;
}
else
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
((AlarmClock)sender).Stop = true;
return;
}
}
}
else
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.WriteLine(" Let alarm ring? Enter Y");
Console.WriteLine(" Stop Alarm? Enter Q");
String input = Console.ReadLine();
if (input.Equals("Y") || input.Equals("y")) return;
else
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
((AlarmClock)sender).Stop = true;
return;
}
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// The driver class that hooks up the event handling method of
// WakeMeUp to the alarm event of an Alarm object using a delegate.
// In a forms-based application, the driver class is the
// form.
// 驱动类
public class AlarmDriver
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
public static void Main(string[] args)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
// Instantiates the event receiver.
// 初始化事件接受者
WakeMeUp w = new WakeMeUp();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// Instantiates the event source.
// 初始化事件发生者
AlarmClock clock = new AlarmClock();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// Wires the AlarmRang method to the Alarm event.
//
clock.Alarm += new AlarmEventHandler(w.AlarmRang);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
clock.Start();
}
}
}
分析:
1、包含事件数据的类AlarmEventArgs,从EventArgs继承,主要有三个属性:闹铃响的次数,是否按下闹铃按钮,闹钟提醒语。
2、public delegate void AlarmEventHandler(object sender, AlarmEventArgs e); // 声明一个委托,sender是发送者,这里指闹钟;AlarmEventArgs包含事件数据的类,以传递详细信息。
3、AlarmClock闹钟类,包括按下、关闭属性,Start()方法,OnAlarm()方法。
public
event AlarmEventHandler Alarm; // AlarmEventHandler类型的事件成员
event 关键字用于指定事件,向类中添加事件需要使用 event 关键字,并提供委托类型和事件名称
在Start()方法中,首先实例化一个包含事件数据的类
AlarmEventArgs e = new AlarmEventArgs(snoozePressed,nrings);
然后调用OnAlarm()方法, 唤醒事件Alarm(this, e);
4、WakeMeUp类的AlarmRang方法操作闹铃事件,此方法可以改变AlarmClock的属性。
AlarmRang(object sender, AlarmEventArgs e) //
5、事件发送器:AlarmClock clock = new AlarmClock();
事件接受器:WakeMeUp w = new WakeMeUp();
将事件发送器和接受器连接起来:clock.Alarm += new AlarmEventHandler(w.AlarmRang);
总结:
事件是类用来通知对象需要执行某种操作的方式。
尽管事件在其他时候(如信号状态更改)也很有用,事件通常还是用在图形用户界面中。
事件通常使用委托事件处理程序进行声明。
事件可以调用匿名方法来替代委托。
毛毛的小窝