路由事件概述 (WPF .NET)

这三个按钮中的每一个都是潜在的 Click 事件源。单击其中一个按钮时,它会引发从按钮到根元素的冒泡事件。Button 和 Border 元素没有附加事件处理程序,但 StackPanel 有。可能树中未显示的其他元素也附加了事件处理程序。当事件到达元素时,WPF 事件系统将调用附加到该元素的处理程序。示例中事件的事件路由为:-> -> -> 个连续的父元素。ClickClickClickStackPanelYesNoCancelButton_ClickClickButtonStackPanelBorderWindows Presentation Foundation (WPF) 应用程序开发人员和组件作者可以使用路由事件通过元素树传播事件,并在树中的多个侦听器上调用事件处理程序。在公共语言运行时 (CLR) 事件中找不到这些功能。多个 WPF 事件是路由事件,例如 ButtonBase.Click。

先决条件

本文假定您具备公共语言运行时 (CLR)、面向对象编程以及如何将 WPF 元素布局概念化为树的基本知识。若要按照本文中的示例进行操作,如果您熟悉可扩展应用程序标记语言 (XAML) 并知道如何编写 WPF 应用程序,则会有所帮助。

什么是路由事件?

您可以从功能或实现的角度考虑路由事件:

  • 功能角度来看,路由事件是一种事件类型,它可以在元素树中的多个侦听器上调用处理程序,而不仅仅是在事件源上。事件侦听器是附加和调用事件处理程序的元素。事件源是最初引发事件的元素或对象。

  • 实现的角度来看,路由事件是在 WPF 事件系统中注册的事件,由 RoutedEvent 类的实例提供支持,并由 WPF 事件系统进行处理。通常,路由事件是使用 CLR 事件“包装器”实现的,以便像在 CLR 事件一样在 XAML 和代码隐藏中启用附加处理程序。

WPF 应用程序通常包含许多元素,这些元素要么在 XAML 中声明,要么在代码中实例化。应用程序的元素存在于其元素树中。根据路由事件的定义方式,当在源元素上引发事件时,它会:

  • 通过元素树从源元素到根元素(通常是页面或窗口)的气泡。
  • 通过元素树从根元素到源元素的隧道向下。
  • 不遍历元素树,仅发生在源元素上。

请考虑以下部分元素树:


   
       
       
       
   

元素树呈现如下所示:

“是”、“否”和“取消”按钮。

这三个按钮中的每一个都是潜在的 Click 事件源。单击其中一个按钮时,它会引发从按钮到根元素的冒泡事件。Button 和 Border 元素没有附加事件处理程序,但 StackPanel 有。可能树中未显示的其他元素也附加了事件处理程序。当事件到达元素时,WPF 事件系统将调用附加到该元素的处理程序。示例中事件的事件路由为:-> -> -> 个连续的父元素。ClickClickClickStackPanelYesNoCancelButton_ClickClickButtonStackPanelBorder

 注意

最初引发路由事件的元素在事件处理程序参数中被标识为 RoutedEventArgs.Source。事件侦听器是附加和调用事件处理程序的元素,在事件处理程序参数中标识为发送方。

路由事件的顶级方案

下面是激发路由事件概念的一些方案,并将其与典型的 CLR 事件区分开来:

  • 控件组合和封装:WPF 中的各种控件具有丰富的内容模型。例如,您可以将图像放置在 Button 中,从而有效地扩展按钮的可视化树。但是,添加的图像不得破坏按钮的命中测试行为,当用户单击图像像素时,按钮需要做出响应。

  • 单个处理程序连接点:可以为每个按钮的事件注册一个处理程序,但对于路由事件,可以附加单个处理程序,如前面的 XAML 示例所示。这使您能够更改单数处理程序下的元素树,例如添加或删除更多按钮,而无需注册每个按钮的事件。引发事件时,处理程序逻辑可以确定事件的来源。在前面显示的 XAML 元素树中指定的以下处理程序包含该逻辑:ClickClickClick

  • private void YesNoCancelButton_Click(object sender, RoutedEventArgs e)
    {
        FrameworkElement sourceFrameworkElement = e.Source as FrameworkElement;
        switch (sourceFrameworkElement.Name)
        {
            case "YesButton":
                // YesButton logic.
                break;
            case "NoButton":
                // NoButton logic.
                break;
            case "CancelButton":
                // CancelButton logic.
                break;
        }
        e.Handled = true;
    }

  • 类处理:路由事件支持您在类中定义的类事件处理程序。类处理程序在类的任何实例上处理同一事件的任何实例处理程序之前处理事件。

  • 引用不带反射的事件:每个路由事件都会创建一个 RoutedEvent 字段标识符,以提供可靠的事件识别技术,该技术不需要静态或运行时反射来识别事件。

  • 如何实现路由事件

  • 路由事件是在 WPF 事件系统中注册的事件,由 RoutedEvent 类的实例提供支持,并由 WPF 事件系统处理。从注册中获取的实例通常存储为注册它的类的成员。该类称为事件“所有者”类。通常,路由事件实现同名的 CLR 事件“包装器”。CLR 事件包装包含和访问器,用于通过特定于语言的事件语法在 XAML 和代码隐藏中启用附加处理程序。和 访问器重写其 CLR 实现,并调用路由事件 AddHandler 和 RemoveHandler 方法。路由事件支持和连接机制在概念上类似于依赖项属性是由 DependencyProperty 类支持并向 WPF 属性系统注册的 CLR 属性。RoutedEventpublic stati

你可能感兴趣的:(wpf,路由事件)