Visual Basic 和 WPF 事件处理

对于 Microsoft Visual Basic .NET 语言(仅),可以使用语言特定的 Handles 关键字将事件处理程序与实例关联,而不是通过特性或使用 AddHandler 方法附加事件处理程序。 但是,用于将处理程序附加到实例的 Handles 技术存在一些限制,因为 Handles 语法不支持 WPF 事件系统的某些特定路由事件功能。

在 WPF 应用程序中使用“Handles”

通过 Handles 连接到实例和事件的事件处理程序必须全部在实例的分部类声明中定义,此要求也适用于通过元素上的特性值进行分配的事件处理程序。 只能为页面上具有 Name 属性值(或声明了 x:Name 指令)的元素指定 Handles。 这是因为 XAML 中的 Name 创建实例引用,该实例引用对于支持 Handles 语法所需的 Instance.Event 引用格式是非常必要的。 可用于 Handles 且不具有 Name 引用的唯一元素是用于定义分部类的根元素实例。

可以通过使用逗号分隔 Handles 后面的 Instance.Event 引用,向多个元素分配相同的处理程序。

可以使用 Handles 将多个处理程序分配给同一 Instance.Event 引用。 请勿对 Handles 引用中特定处理程序的提供顺序赋予任何重要性;应假定可按任何顺序调用处理相同事件的处理程序。

若要删除声明中通过 Handles 添加的处理程序,可调用 RemoveHandler

如果要将处理程序附加到实例成员表中用于定义要处理的事件的实例,可使用 Handles 附加路由事件的处理程序。 对于路由事件,通过 Handles 附加的处理程序遵循的路由规则与附加为 XAML 特性或使用 AddHandler 公共签名附加的处理程序所遵循的路由规则相同。 这意味着如果事件已标记为已处理(事件数据中的 Handled 属性为 True),则不会调用通过 Handles 附加的处理程序来响应该事件实例。 可通过路由中另一个元素上的实例处理程序,或通过在路由中当前元素或更早元素上进行类处理,将事件标记为已处理。 对于可支持成对的隧道事件/冒泡事件的输入事件,隧道路由可能已将事件对标记为已处理。 有关路由事件的详细信息,请参阅路由事件概述

添加处理程序时的“Handles”限制

Handles 无法引用附加事件的处理程序。 必须对该附加事件使用 add 访问方法,或使用 XAML 中的 typename.eventname 事件特性。 有关详细信息,请参阅路由事件概述

对于路由事件,只能使用 Handles 为实例成员表中存在该事件的实例分配处理程序。 但是,对于一般的路由事件,父元素可以是来自子元素的事件的侦听器,即使该父元素的成员表中没有此事件也是如此。 在特性语法中,这可以通过 typename.membername 特性形式来指定,此形式限定哪种类型实际定义要处理的事件。 例如,某个父 Page(未定义 Click 事件)可以通过分配 Button.Click 形式的特性处理程序来侦听按钮单击事件。 但 Handles 不支持 typename.membername 形式,因为它必须支持与该形式冲突的 Instance.Event 形式。 有关详细信息,请参阅路由事件概述

Handles 无法附加针对标记为已处理的事件而调用的处理程序。 必须使用代码并调用 AddHandler(RoutedEvent, Delegate, Boolean)handledEventsToo 重载。

注意

在 XAML 中为相同事件指定事件处理程序时,请勿在 Visual Basic 代码中使用 Handles 语法。 在这种情况下,将调用事件处理程序两次。

WPF 如何实现“Handles”功能

编译 Extensible Application Markup Language (XAML) 页时,中间文件会声明对页中设置了 Name 属性(或声明了 x:Name 指令)的每个元素的 FriendWithEvents 引用。 每个命名实例都可能是可通过 Handles 分配给处理程序的元素。

注意

在 Visual Studio 中,IntelliSense 可完整显示可用于页中的 Handles 引用的全部元素。 但是,这可能需要执行一个编译传递,以便中间文件可以填充所有 Friends 引用。

另请参阅