【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 事件注册调用中设置路由策略。

  • 25
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吉特思米(gitusme)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值