预览事件
预览事件(也称为隧道事件)是路由事件,其中路由的方向是从应用程序根到引发事件的元素,并在事件数据中报告为源。 并非所有事件方案都支持或需要预览事件;本主题介绍存在预览事件的情况,应用程序或组件应如何处理它们,以及可能适合在自定义组件或类中创建预览事件的情况。
预览事件和输入
通常处理预览事件时,请谨慎标记事件数据中处理的事件。 在引发预览事件的元素(在事件数据中被报告为源的元素)以外的任何元素上处理预览事件会导致不向元素提供处理其发起的事件的机会。 有时,这是期望的结果,尤其是当问题元素存在于控件组合内的关系中时。
具体而言,对于输入事件,预览事件还与等效的浮升事件共享事件数据实例。 如果使用预览事件类处理程序将输入事件标记为已处理,则不会调用浮升输入事件类处理程序。 或者,如果使用预览事件实例处理程序将事件标记为已处理,则通常不会调用浮升事件的处理程序。 即使事件被标记为已处理,也可为类处理程序或实例处理程序注册或附加一个要调用的选项,但这种方法并不常用。
有关类处理及其与预览事件的关系的详细信息,请参阅将路由事件标记为“已处理”和类处理。
通过控件解决事件禁止问题
通常使用预览事件的一种情况是对输入事件进行复合控件处理。 有时,控件的作者会禁止特定事件源自其控件,或许是为了替换包含更多信息或暗示更具体行为的组件定义事件。 例如,Windows Presentation Foundation (WPF) Button 禁止 Button 或其复合元素引发 MouseLeftButtonDown 或 MouseRightButtonDown 浮升事件,支持捕获鼠标并引发始终由 Button 自身引发的 Click 事件。 事件及其数据仍沿路由继续,但由于 Button 将事件数据标记为 Handled,因此只调用专门指示应在 handledEventsToo
情况下执行操作的事件的处理程序。 如果应用程序根的其他元素仍然希望有机会处理受控件抑制的事件,一种替代方法是在代码中附加处理程序,并将 handledEventsToo
指定为 true
。 但通常更简单的方法是将你处理的路由方向更改为输入事件的预览等效项。 例如,如果控件禁止 MouseLeftButtonDown,请尝试改为附加 PreviewMouseLeftButtonDown 的处理程序。 此方法仅适用于基元素输入事件,例如 MouseLeftButtonDown。 这些输入事件使用隧道/浮升对,引发这两个事件并共享事件数据。
上述每种方法都有副作用或限制。 处理预览事件的副作用是处理当时的事件可能会禁用预期处理浮升事件的处理程序,因此限制是,当事件仍在路由的预览部分时将其标记为已处理通常不是一个好主意。 handledEventsToo
方法的限制是,不能在 XAML 中将 handledEventsToo
处理程序指定为属性,在获取要附加处理程序的元素的对象引用后,必须在代码中注册事件处理程序。