【WPF.NET开发】如何创建自定义路由事件

本文内容

  1. 先决条件
  2. 路由事件步骤
  3. 示例

Windows Presentation Foundation (WPF) 应用程序开发人员和组件作者可以创建自定义路由事件,用于扩展公共语言运行时 (CLR) 事件的功能。 本文介绍创建自定义路由事件的基本知识。

1、先决条件

本文假定你对路由事件有基本的了解,并且已阅读
路由事件概述。 若要遵循本文中的示例,如果熟悉 Extensible Application Markup Language (XAML) 并知道如何编写 Windows Presentation Foundation (WPF) 应用程序,将会很有帮助。

2、路由事件步骤

创建路由事件的基本步骤如下:

  1. 使用 RegisterRoutedEvent 方法注册 RoutedEvent

  2. 注册调用返回一个 RoutedEvent 实例,称为路由事件标识符,该标识符包含已注册的事件名、路由策略
    和其他事件详细信息。 将该标识符分配给静态只读字段。 按照惯例:

    • 具有浮升
      策略的路由事件的标识符命名为 <event name>Event。 例如,如果事件名为 Tap,则标识符应命名为 TapEvent
    • 具有
      隧道策略的路由事件的标识符命名为 Preview<event name>Event。 例如,如果事件名为 Tap,则标识符应命名为 PreviewTapEvent
  3. 定义 CLR add 和 remove 事件访问器。 如果没有 CLR 事件访问器,你就只能通过直接调用 UIElement.AddHandler 和 UIElement.RemoveHandler 方法来添加或删除事件处理程序。 使用 CLR 事件访问器时,你会获得以下事件处理程序分配机制:

    • 对于 Extensible Application Markup Language (XAML),可以使用属性语法来添加事件处理程序。
    • 对于 C#,可以使用 += 和 -= 运算符来添加或删除事件处理程序。
    • 对于 VB,可以使用 AddHandler 和 RemoveHandler 语句来添加或删除事件处理程序。
  4. 添加用于触发路由事件的自定义逻辑。 例如,你的逻辑可能会基于用户输入和应用程序状态触发事件。

3、示例

以下示例在自定义控件库中实现 CustomButton 类。 派生自 Button 的 CustomButton 类:

  1. 使用 RegisterRoutedEvent 方法注册一个名为 ConditionalClick 的 RoutedEvent,并在注册期间指定浮升
    策略。
  2. 将从注册调用返回的 RoutedEvent 实例分配给名为 ConditionalClickEvent 的静态只读字段。
  3. 定义 CLR add 和 remove 事件访问器。
  4. 添加自定义逻辑,以在单击 CustomButton 并应用外部条件时引发自定义路由事件。 虽然示例代码从重写的 OnClick 虚拟方法内引发 ConditionalClick 路由事件,但你可选用任何方式来引发事件。
public class CustomButton : Button
{
    // Register a custom routed event using the Bubble routing strategy.
    public static readonly RoutedEvent ConditionalClickEvent = EventManager.RegisterRoutedEvent(
        name: "ConditionalClick",
        routingStrategy: RoutingStrategy.Bubble,
        handlerType: typeof(RoutedEventHandler),
        ownerType: typeof(CustomButton));

    // Provide CLR accessors for assigning an event handler.
    public event RoutedEventHandler ConditionalClick
    {
        add { AddHandler(ConditionalClickEvent, value); }
        remove { RemoveHandler(ConditionalClickEvent, value); }
    }

    void RaiseCustomRoutedEvent()
    {
        // Create a RoutedEventArgs instance.
        RoutedEventArgs routedEventArgs = new(routedEvent: ConditionalClickEvent);

        // Raise the event, which will bubble up through the element tree.
        RaiseEvent(routedEventArgs);
    }

    // For demo purposes, we use the Click event as a trigger.
    protected override void OnClick()
    {
        // Some condition combined with the Click event will trigger the ConditionalClick event.
        if (DateTime.Now > new DateTime())
            RaiseCustomRoutedEvent();

        // Call the base class OnClick() method so Click event subscribers are notified.
        base.OnClick();
    }
}

该示例包含一个单独的 WPF 应用程序,该应用程序使用 XAML 标记将 CustomButton 实例添加到 StackPanel,并将 Handler_ConditionalClick 方法分配为 CustomButton 和 StackPanel1 元素的 ConditionalClick 事件处理程序。

<Window x:Class="CodeSample.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:custom="clr-namespace:WpfControl;assembly=WpfControlLibrary"
        Title="How to create a custom routed event" Height="100" Width="300">

    <StackPanel Name="StackPanel1" custom:CustomButton.ConditionalClick="Handler_ConditionalClick">
        <custom:CustomButton
            Name="customButton"
            ConditionalClick="Handler_ConditionalClick"
            Content="Click to trigger a custom routed event"
            Background="LightGray">
        </custom:CustomButton>
    </StackPanel>
</Window>

WPF 应用程序在代码隐藏中定义 Handler_ConditionalClick 事件处理程序方法。 事件处理程序方法只能在代码隐藏中实现。

// The ConditionalClick event handler.
private void Handler_ConditionalClick(object sender, RoutedEventArgs e)
{
    string senderName = ((FrameworkElement)sender).Name;
    string sourceName = ((FrameworkElement)e.Source).Name;

    Debug.WriteLine($"Routed event handler attached to {senderName}, " +
        $"triggered by the ConditionalClick routed event raised on {sourceName}.");
}

// Debug output when CustomButton is clicked:
// Routed event handler attached to CustomButton,
//     triggered by the ConditionalClick routed event raised on CustomButton.
// Routed event handler attached to StackPanel1,
//     triggered by the ConditionalClick routed event raised on CustomButton.

单击 CustomButton 时:

  1. ConditionalClick 路由事件在 CustomButton 上引发。
  2. 触发了附加到 CustomButton 的 Handler_ConditionalClick 事件处理程序。
  3. ConditionalClick 路由事件在元素树中向上遍历到 StackPanel1
  4. 触发了附加到 StackPanel1 的 Handler_ConditionalClick 事件处理程序。
  5. ConditionalClick 路由事件继续向上遍历元素树,可能会触发附加到其他已遍历元素的其他 ConditionalClick 事件处理程序。

Handler_ConditionalClick 事件处理程序获取有关触发它的事件的以下信息:

  • sender 对象,它是事件处理程序附加到的元素。 处理程序首次运行时,sender 为 CustomButton,第二次运行时则为 StackPanel1
  • RoutedEventArgs.Source 对象,它是最初引发事件的元素。 在本示例中,Source 始终为 CustomButton

 备注

路由事件和 CLR 事件之间的一个主要区别是,路由事件遍历元素树来查找处理程序,而 CLR 事件不遍历元素树,处理程序只能附加到引发事件的源对象。 因此,路由事件 sender 可以是元素树中的任何已遍历的元素。

你可以像创建浮升事件一样创建隧道事件,但将在 Tunnel 事件注册调用中设置路由策略。

相关推荐

  1. 【WPF.NET开发如何创建定义事件

    2024-01-03 10:52:04       70 阅读
  2. vue脚手架,,过滤器,定义指令

    2024-01-03 10:52:04       52 阅读
  3. Elasticsearch搜索优化-定义规划(routing)

    2024-01-03 10:52:04       29 阅读
  4. Thinkphp5实现定义和使用方法

    2024-01-03 10:52:04       28 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-03 10:52:04       91 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-03 10:52:04       97 阅读
  3. 在Django里面运行非项目文件

    2024-01-03 10:52:04       78 阅读
  4. Python语言-面向对象

    2024-01-03 10:52:04       88 阅读

热门阅读

  1. 微信养号指南:提高账号权重

    2024-01-03 10:52:04       65 阅读
  2. LDD学习笔记 -- 用户空间 & 内核空间

    2024-01-03 10:52:04       64 阅读
  3. 微信小程序 wx.request二次封装

    2024-01-03 10:52:04       64 阅读
  4. 卸载云服务器上的 MySQL 数据库

    2024-01-03 10:52:04       53 阅读
  5. C++ 拷贝构造函数

    2024-01-03 10:52:04       56 阅读
  6. User mkcert 生成本地证书的步骤

    2024-01-03 10:52:04       64 阅读