事件功能是由三个互相联系的元素提供的:提供事件数据的类、事件委托和引发事件的类。
.NET Framework 具有命名与事件相关的类和方法的约定。如果希望您的类引发一个名为 EventName 的事件,
您需要以下元素:
包含事件数据的类,名为 EventNameEventArgs。该类必须从 System.EventArgs 导出。
事件的委托,名为 EventNameEventHandler。
引发事件的类。该类必须提供事件声明 (EventName) 和引发事件 (OnEventName) 的方法。
.NET Framework 类库或第三方类库中可能已经定义了事件数据类和事件委托类。在这种情况下,您就不需要定义这些类了。
例如,如果您的事件不使用自定义数据,可以使用 System.EventArgs 作为事件数据并使用 System.EventHandler 作为委托。
使用 event 关键字在类中定义事件成员。当编译器在类中遇到 event 关键字时,它会创建一个私有成员,例如:
private EventNameHandler eh = null;
编译器还会创建两个公共方法,即 add_EventName 和 remove_EventName。这些方法是事件挂钩,它们允许委托与
事件委托 eh 合并或从该事件委托中移除。这些详细信息对程序员是隐藏的。
注意
在除 C# 和 Visual Basic 2005 以外的其他语言中,编译器可能不自动生成与事件成员对应的代码,您可能需要显式地
定义事件挂钩和私有委托字段。
定义事件实现后,您必须确定引发事件的时间。通过在定义事件的类或派生类中调用受保护的 OnEventName 方法来引发事件。
OnEventName 方法通过调用委托,传入所有事件特定的数据来引发事件。事件的委托方法可以执行事件操作或处理事件特定的数据。
注意
受保护的 OnEventName 方法也允许派生类重写事件,而不必向其附加委托。派生类必须始终调用基类的 OnEventName 方法
以确保注册的委托接收到事件。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下面的示例程序阐释如何在一个类中引发一个事件,然后在另一个类中处理该事件。AlarmClock 类定义公共事件 Alarm,
并提供引发该事件的方法。AlarmEventArgs 类派生自 EventArgs,并定义 Alarm 事件特定的数据。WakeMeUp 类定义处理 Alarm 事件的
AlarmRang 方法。AlarmDriver 类一起使用类,将使用 WakeMeUp 的 AlarmRang 方法设置为处理 AlarmClock 的 Alarm 事件。
一、AlarmClock 类
public delegate void AlarmEventHandler(object sender, AlarmEventArgs e);
public class AlarmClock
{
private bool snoozePressed = false;
private int nrings = 0;
private bool stop = false;
public bool Stop
{
get { return stop; }
set { stop = value; }
}
public bool SnoozePressed
{
get { return snoozePressed; }
set { snoozePressed = value; }
}
public event AlarmEventHandler Alarm;
protected virtual void OnAlarm(AlarmEventArgs e)
{
if (Alarm != null)
{
// Invokes the delegates.
Alarm(this, e);
}
}
public void Start()
{
for (; ; )
{
nrings++;
if (stop)
{
break;
}
else if (snoozePressed)
{
System.Threading.Thread.Sleep(1000);
{
AlarmEventArgs e = new AlarmEventArgs(snoozePressed,
nrings);
OnAlarm(e);
}
}
else
{
System.Threading.Thread.Sleep(300);
AlarmEventArgs e = new AlarmEventArgs(snoozePressed,
nrings);
OnAlarm(e);
}
}
}
}
二、AlarmEventArgs类
public class AlarmEventArgs : EventArgs
{
private readonly bool snoozePressed;
private readonly int nrings;
public AlarmEventArgs(bool snoozePressed, int nrings)
{
this.snoozePressed = snoozePressed;
this.nrings = nrings;
}
public int NumRings
{
get { return nrings; }
}
public bool SnoozePressed
{
get { return snoozePressed; }
}
public string AlarmText
{
get
{
if (snoozePressed)
{
return ("Wake Up!!! Snooze time is over.");
}
else
{
return ("Wake Up!");
}
}
}
}
三、WakeMeUp类
public class WakeMeUp
{
public void AlarmRang(object sender, AlarmEventArgs e)
{
Console.WriteLine(e.AlarmText + "\n");
if (!(e.SnoozePressed))
{
if (e.NumRings % 10 == 0)
{
Console.WriteLine(" Let alarm ring? Enter Y");
Console.WriteLine(" Press Snooze? Enter N");
Console.WriteLine(" Stop Alarm? Enter Q");
String input = Console.ReadLine();
if (input.Equals("Y") || input.Equals("y")) return;
else if (input.Equals("N") || input.Equals("n"))
{
((AlarmClock)sender).SnoozePressed = true;
return;
}
else
{
((AlarmClock)sender).Stop = true;
return;
}
}
}
else
{
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
{
((AlarmClock)sender).Stop = true;
return;
}
}
}
}
四、AlarmDriver类
public class AlarmDriver
{
public static void Main(string[] args)
{
WakeMeUp w = new WakeMeUp();
AlarmClock clock = new AlarmClock();
clock.Alarm += new AlarmEventHandler(w.AlarmRang);
clock.Start();
}
}