WPF 路由事件和附加事件简明教程

一、路由事件

1.1、定义

概括:可在 WPF 元素树中传递的事件,支持界面绑定处理方法。.

代码:

public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent("Tap", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(OwnerType));/// <summary>/// [路由事件]注释/// </summary>public event RoutedEventHandler Tap { add => AddHandler(TapEvent, value); remove => RemoveHandler(TapEvent, value); }/// <summary>/// 路由事件 注释 的触发方法/// </summary>/// <param name="originalSource">此参数会传递到事件参数的 OriginalSource 属性中</param>private void RaiseTapEvent(object originalSource = null){  RaiseEvent(new RoutedEventArgs(RangeSelectedEvent, originalSource));}

1.2、使用示例

定义事件:

WPF 路由事件和附加事件简明教程

方法一、使用后台事件

此事件定义在窗口后台类中,在前台使用时还是需要使用完全限定名:

WPF 路由事件和附加事件简明教程

引发事件时将数据类传进去了,用处理方法的 e.OriginalSource 就能取到了:

WPF 路由事件和附加事件简明教程

方法二、使用事件转命令绑定

EventName 仅需要事件名称即可,不需要完全限定名了;绑定命令,EventArgsParameterPath 设置为 "OriginalSource",这样就能获取到对应的参数了:

WPF 路由事件和附加事件简明教程

命令定义及处理方法中都指定了对应类型的参数:

WPF 路由事件和附加事件简明教程

二、附加事件

2.1、定义

概括:可在普通类(非 UIElement 子类)中定义的路由事件。

代码:

public class AttachedEventHelper{    #region 附加事件
    public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AutoTableEventHelper));    public static void AddValueChangedHandler(DependencyObject dependencyObject, RoutedEventHandler handler)    {        if (dependencyObject is not UIElement uiElement)            return;        uiElement.AddHandler(ValueChangedEvent, handler);    }    public static void RemoveValueChangedHandler(DependencyObject dependencyObject, RoutedEventHandler handler)    {        if (dependencyObject is not UIElement uiElement)            return;        uiElement.RemoveHandler(ValueChangedEvent, handler);    }
    #endregion}

图示:

WPF 路由事件和附加事件简明教程

2.2、绑定处理程序

WPF 路由事件和附加事件简明教程

和普通路由事件同理,可以使用代码隐藏页的方法绑定处理方法,也可以使用事件转命令方式绑定。

2.3、触发事件

触发方法和普通路由事件相同,传递的参数也是到 OriginalSource 中去的:

WPF 路由事件和附加事件简明教程

注意:以下两段未严谨验证,仅依据现有知识和实际现象推断,大家自行把握。

和普通路由事件触发的不同之处在于,前面需要指定触发源元素对象,不然可能会进不了事件处理方法。原因应该是这样的,由于事件定义为了冒泡事件,所以是从内层元素向外层传递的,所以如果处理方法写在事件触发元素的内层或同一层 (上图中如果不写 tb 就是同一层了),那么处理方法就接受不到消息了。

所以可以总结一下,附加事件是一种定义的时候写法特殊一些的路由事件,可定义在普通类中。触发事件和接收事件时使用完全限定名,且两者都不限制是在哪个 UI 元素上,不过需要依据事件的类型(冒泡还是隧道)来合理安排两者分别放置在什么层级的元素上,具体来说就是,如果是冒泡事件则触发元素在接收元素内层,如果是隧道事件则触发元素在接收元素外层。可以看出,使用路由事件的好处之一就是可灵活放置接收处理消息方法的位置。

三、资源

官方对于依赖属性(propdp)和附加属性(propa)都提供了代码片段,使用方法就是输入对应的快捷键后按一次或两次 Tab,就能插入了;或者在代码编辑窗口,按 Ctrl K X 进行选择:

WPF 路由事件和附加事件简明教程

但是对于路由事件、附加事件等,官方好像没有提供代码片段,只能自己生成了,推荐使用 Code Snippest Studio 扩展插件来生成:

WPF 路由事件和附加事件简明教程

生成的代码片段文件后缀为 .snippet,保存到某个文件夹后,打开 VS--> 工具 --> 代码片段管理器,添加上这个文件夹即可使用了:

WPF 路由事件和附加事件简明教程

如下图所示:

WPF 路由事件和附加事件简明教程

本次主要生成了 路由事件(wpfre)、附加事件(wpfae),还附赠改进的代码片段 依赖属性(wpfdp)、附加属性(wpfap),以及某种情况下适用的 通知属性(wpfp)。

好消息是,本人已将这些代码片段打包上传到百度云盘了,下载地址可在微信公众号 “独立观察员博客(DLGCY_BLOG)” 消息框回复 “代码片段” 获取。