处理和引发事件 Handling and raising events

有关在 Windows 8.x Store 应用中处理事件的信息,请参阅事件和路由事件概述)。

事件是由对象发送的用于发出操作信号的消息。该操作可能是由用户交互引起,例如单击按钮;也可能是由某些其他程序的逻辑导致,例如更改属性值。引发事件的对象称为“事件发送方”。事件发送方不知道哪个对象或方法将接收(处理)它引发的事件。事件通常是事件发送方的成员,例如 事件是 Button 类的成员, 事件是实现 INotifyPropertyChanged 接口的类的成员。

若要定义一个事件,可以在事件类签名中使用 (在 C# 中)或 Event(在 Visual Basic 中)关键字,并指定事件的委托类型。委托在下一节中介绍。

通常,为了引发事件,您可以在 C# 中添加一个标记为 protectedvirtual 或在 Visual Basic 中标记为 ProtectedOverridable 的方法。将此方法命名为 OnEventName;例如,OnDataReceived此方法应接受一个指定事件数据对象( 类型或派生类型)的参数。您提供此方法以允许派生类重写引发事件的逻辑。派生类应始终调用基类的 OnEventName 方法,以确保注册的委托接收事件。

  1. Public Class Counter
  2. Public Event ThresholdReached As EventHandler
  3. End Sub
  4. ' provide remaining implementation for the class
  5. End Class

委托Delegates

委托是一种保存对方法的引用的类型。委托是通过显示所引用方法的返回类型和参数的签名来声明的,并可以仅保存与其签名匹配的方法的引用。因此,委托等同于类型安全函数指针或回叫。委托声明足以定义委托类。

委托在 .NET 中有许多用途。在事件上下文中,委托是事件源和处理事件的代码之间的媒介(或类似指针的机制)。如上一节的例子所示,可以通过在事件声明中包括委托类型来将委托和事件相关联。有关委托的详细信息,请参阅 Delegate 类。

.NET 提供了 和 EventHandler<TEventArgs> 委托来支持大部分事件场景。使用 委托处理不包含事件数据的所有事件。使用 EventHandler<TEventArgs> 委托处理包含事件相关数据的事件。这些委托没有返回类型值,并且接受两个参数(事件源的对象和事件数据的对象)。

委托是,这意味着它们可以保存对多个事件处理方法的引用。有关详细信息,请参阅 Delegate 参考页。委托提供了事件处理中的灵活性和精确控制。委托人通过维护事件的已注册事件处理程序列表来充当引发事件的类的事件调度程序。

  1. Public Delegate Sub ThresholdReachedEventHandler(sender As Object, e As ThresholdReachedEventArgs)

与事件相关的数据可以通过事件数据类提供。.NET 提供了许多事件数据类,用户可以在自己的应用程序中使用它们。例如, 类是 SerialPort.DataReceived 事件的事件数据类。.NET 遵循所有事件数据类以 EventArgs 结尾的命名模式。您通过查看事件的委托来确定哪个事件数据类与事件相关联。例如, 委托包含 SerialDataReceivedEventArgs 类作为它的一个参数。 类是所有事件数据类的基类型。当一个事件没有任何与其相关联的数据时,您也会用到 类。当您创建一个事件仅用来通知其他类出问题了,不需要传递任何数据时,请包括 类作为委托中的第二个参数。当没有数据提供时,您可以传递 值。 委托包括 类作为一个参数。当您想创建一个自定义的事件数据类时,请创建一个派生自 的类,然后提供所需的所有成员,来传递与该事件相关的数据。通常,应使用与 .NET 相同的命名模式,并且事件数据类名称应以 EventArgs 结尾。下面的示例演示了一个名为 ThresholdReachedEventArgs 的事件数据类。它包含特定于引发事件的属性。 [!code-csharp][!code-vbEventsOverview#3] ## 事件处理程序 若要响应事件,您需要在事件接收器中定义一个事件处理程序方法。此方法必须与您正处理的事件的委托签名匹配。在事件处理程序中,当事件引发时会执行所需操作,例如在用户单击按钮之后收集用户输入。若当事件发生时收到通知,您的事件处理程序方法必须订阅该事件。

下面的示例演示与 c_ThresholdReached 委托的签名匹配的 EventHandler 事件处理程序方法。该方法订阅 事件。

  1. Module Module1
  2. Sub Main()
  3. Dim c As New Counter()
  4. AddHandler c.ThresholdReached, AddressOf c_ThresholdReached
  5. ' provide remaining implementation for the class
  6. Sub c_ThresholdReached(sender As Object, e As EventArgs)
  7. Console.WriteLine("The threshold was reached.")
  8. End Sub
  9. End Module

静态和动态事件处理程序Static and dynamic event handlers

借助 .NET,订阅者可以进行静态或动态注册以获得事件通知。对于其事件由静态事件处理程序进行处理的类,静态事件处理程序对其整个生命周期有效。通常为响应某些条件程序逻辑,会在程序执行期间显式激活和停用动态事件处理程序。例如,如果仅在特定条件下需要事件通知,或如果应用程序提供多个事件处理程序且由运行时条件定义要使用的适当事件处理程序,则可以使用动态事件处理程序。上一节中的示例演示如何动态添加事件处理程序。有关详细信息,请查看 Visual Basic 中的和 C# 中的事件

如果您的类引发多个事件,编译器会为每一个事件委托实例生成一个字段。如果事件数量很大,则可能无法接受按一个委托计算一个字段的存储成本。对于这些情况,.NET 提供一个事件属性,可以将其与选择的另一数据结构一起用于存储事件委托。

相关主题Related topics