您的位置:首页 > 其它

WPF基础之路由事件三

2012-05-10 17:35 211 查看
“已处理”概念
所有的路由事件都共享一个公用的事件数据基类 RoutedEventArgs。RoutedEventArgs 定义了一个采用布尔值的 Handled 属性。Handled 属性的目的在于,允许路由中的任何事件处理程序通过将 Handled 的值设置为 true 来将路由事件标记为“已处理”。处理程序在路由路径上的某个元素处对共享事件数据进行处理之后,这些数据将再次报告给路由路径上的每个侦听器。

Handled 的值影响路由事件在沿路由线路向远处传播时的报告或处理方式。在路由事件的事件数据中,如果 Handled 为 true,则通常不再为该特定事件实例调用负责在其他元素上侦听该路由事件的处理程序。这条规则对以下两类处理程序均适用:在 XAML 中附加的处理程序;由语言特定的事件处理程序附加语法(如 += 或 Handles)添加的处理程序。对于最常见的处理程序方案,如果将 Handled 设置为 true,以此将事件标记为“已处理”,则将“停止”隧道路由或冒泡路由,同时,类处理程序在某个路由点处处理的所有事件的路由也将“停止”。

但是,侦听器仍可以凭借“handledEventsToo”机制来运行处理程序,以便在事件数据中的 Handled 为 true 时响应路由事件。换言之,将事件数据标记为“已处理”并不会真的停止事件路由。您只能在代码或 EventSetter 中使用 handledEventsToo 机制:

在代码中,不使用适用于一般 CLR 事件的特定于语言的事件语法,而是通过调用 WPF 方法 AddHandler(RoutedEvent, Delegate, Boolean) 来添加处理程序。使用此方法时,请将 handledEventsToo 的值指定为 true。

在 EventSetter 中,请将 HandledEventsToo 属性设置为 true。

除了 Handled 状态在路由事件中生成的行为以外,Handled 概念还暗示您应当如何设计自己的应用程序和编写事件处理程序代码。可以将 Handled 概念化为由路由事件公开的简单协议。此协议的具体使用方法由您来决定,但是需要按照如下方式来对 Handled 值的预期使用方式进行概念设计:

如果路由事件标记为“已处理”,则它不必由该路由中的其他元素再次处理。

如果路由事件未标记为“已处理”,则说明该路由中前面的其他侦听器已经选择了不注册处理程序,或者已经注册的处理程序选择不操作事件数据并将 Handled 设置为 true。(或者,当前的侦听器很可能就是路由中的第一个点。) 当前侦听器上的处理程序现在有三个可能的操作方案:

不执行任何操作;该事件保持未处理状态,该事件将路由到下一个侦听器。

执行代码以响应该事件,但是所执行的操作被视为不足以保证将事件标记为“已处理”。该事件将路由到下一个侦听器。

执行代码以响应该事件。在传递到处理程序的事件数据中将该事件标记为“已处理”,因为所执行的操作被视为不足以保证将该事件标记为“已处理”。该事件仍将路由到下一个侦听器,但是,由于其事件数据中存在 Handled=true,因此只有 handledEventsToo 侦听器才有机会调用进一步的处理程序。

这个概念设计是通过前面提到的路由行为来加强的:即使路由中前面的处理程序已经将 Handled 设置为 true,也会增加为所调用的路由事件附加处理程序的难度(尽管仍可以在代码或样式中实现这一目的)。

有关 Handled、路由事件的类处理的更多信息,以及针对何时适合将路由事件标记为 Handled 的建议,请参见将路由事件标记为已处理以及类处理。

在应用程序中,相当常见的做法是只针对引发冒泡路由事件的对象来处理该事件,而根本不考虑事件的路由特征。但是,在事件数据中将路由事件标记为“已处理”仍是一个不错的做法,因为这样可以防止元素树中位置更高的元素也对同一个路由事件附加了处理程序而出现意外的副作用。

类处理程序
如果您定义的类是以某种方式从 DependencyObject 派生的,那么对于作为类的已声明或已继承事件成员的路由事件,还可以定义和附加一个类处理程序。每当路由事件到达其路由中的元素实例时,都会先调用类处理程序,然后再调用附加到该类某个实例的任何实例侦听器处理程序。

有些 WPF 控件对某些路由事件具有固有的类处理。路由事件可能看起来从未引发过,但实际上正对其进行类处理,如果您使用某些技术的话,路由事件可能仍由实例处理程序进行处理。同样,许多基类和控件都公开可用来重写类处理行为的虚方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: