wpf 事件与附加事件

事件沿着可视化树(Visual Tree)传播,而不是仅限于触发事件的对象本身。有以下几种类型

冒泡(Bubbling) :事件从触发源(如按钮)向上传播到父级容器(如窗口)。
隧道(Tunneling) :事件从根容器向下传播到触发源。
直接(Direct) :类似于传统事件,仅在触发源上处理。

注册事件


// 1. 定义路由事件参数类
// 2. 注册路由事件
// 2.2 定义路由事件附加静态辅助方法, 这样才能在 XAML 中使用
// 3. 触发路由事件
// 4 使用代码或是 xaml 中定义事件处理函数

// 1. 定义路由事件参数类
public class ReportTimeRoutedEventArgs(RoutedEvent routedEvent, object source) : RoutedEventArgs(routedEvent, source)
{
    public DateTime ReportTime { get; set; }
}

   // 2. 注册路由事件
    public static readonly RoutedEvent ReportTimeEvent = EventManager.RegisterRoutedEvent("ReportTime", RoutingStrategy.Bubble,
        typeof(EventHandler<ReportTimeRoutedEventArgs>), typeof(ReportTimeButton));

    // 2.1 定义路由事件属性,兼容 CRL 的事件处理方式 
    public event EventHandler<ReportTimeRoutedEventArgs> ReportTime
    {
        add => this.AddHandler(ReportTimeEvent, value);
        remove => this.RemoveHandler(ReportTimeEvent, value);
    }

    // 2.2 定义路由事件附加辅助方法, 这样才能在 XAML 中使用
    public static void AddReportTimeHandler(DependencyObject d, RoutedEventHandler handler)
    {
        if (d is UIElement uiElement)
        {
            uiElement.AddHandler(ReportTimeEvent, handler);
        }
    }

    // 2.2 定义路由事件附加辅助方法, 这样才能在 XAML 中使用
    public static void RemoveReportTimeHandler(DependencyObject d, RoutedEventHandler handler)
    {
        if (d is UIElement uiElement)
        {
            uiElement.RemoveHandler(ReportTimeEvent, handler);
        }
    }

订阅事件


// 4.1 订阅路由事件
this.AddHandler(ReportTimeButton.ReportTimeEvent, new RoutedEventHandler(this.ReportTimeButton_ReportTime));

<!-- 4.2 xaml 中订阅事件 -->
<Grid Margin="24" routedEventDemo:ReportTimeButton.ReportTime="ReportTimeButton_OnReportTime">

引发事件


// 3. 触发路由事件
        this.RaiseEvent(new ReportTimeRoutedEventArgs(ReportTimeEvent, this) { ReportTime = DateTime.Now });

// 3. 触发路由事件
uiElement.RaiseEvent(new ReportTimeRoutedEventArgs(ReportTimeButton.ReportTimeEvent, uiElement) { ReportTime = DateTime.Now });

附加事件

事件引发函数 RaiseEvent 定义在 UIElement 中,如果非 UIElement 类需要事件的话,可以在类中定义事件,只是引发由三方 UIElement 控件引发

    // 这里使用 RoutedPropertyChangedEventHandler
    public static readonly RoutedEvent ColorChangedEvent = EventManager.RegisterRoutedEvent(nameof(ColorChanged), outingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<Color>), typeof(ColorPickerControl));

    // CLR 事件
    public event RoutedPropertyChangedEventHandler<Color> ColorChanged
    {
        add => this.AddHandler(ColorChangedEvent, value);
        remove => this.RemoveHandler(ColorChangedEvent, value);
    }

    // 为了 xaml 中自动提示
    public static void AddColorChangedHandler(DependencyObject d, RoutedEventHandler handler)
    {
        if (d is UIElement uiElement)
        {
            uiElement.AddHandler(ColorChangedEvent, handler);
        }
    }

    // 为了 xaml 中自动提示
    public static void RemoveColorChangedHandler(DependencyObject d, RoutedEventHandler handler)
    {
        if (d is UIElement uiElement)
        {
            uiElement.RemoveHandler(ColorChangedEvent, handler);
        }
    }

    // 引发事件
    public static void OnColorChanged(UiElement element, Color lastColor, Color newColor)
    {
        var eventArgs = new RoutedPropertyChangedEventArgs<Color>(lastColor, newColor, ColorChangedEvent)
        {
            Source = this,
        };

        element.RaiseEvent(eventArgs);
    }
上一篇
下一篇