WPF自定义路由事件

2021年09月15日 阅读数:2
这篇文章主要向大家介绍WPF自定义路由事件,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

    了解了路由事件后,这节来学习一下如何自定义路由事件。编辑器

 

【分析代码】

    在演示代码前,咱们不妨先看一段Button按钮的Click路由事件源码,从源码中学习一下如何定义路由事件。ide

    在ButtonBase中,跟Click路由事件相关的有以下四处代码:学习

代码一this

代码二spa

代码三code

代码四orm

    第一段是声明了ClickEvent这一路由事件对象,这个不用多说;对象

    第二段是声明了ClickEvent路由事件对象的包装器,它相似于属性的get,set,方便咱们从外部把路由事件的处理器附加到路由事件上。当外部进行“+=”操做时,内部就会执行add块,将事件处理附加到Click路由事件上,反之执行“-=”操做时,会执行remove块中的内容;blog

    第三段是构造方法中构建Click路由事件对象,跟建立依赖对象相似的是,路由事件对象的建立也不是直接new,而是经过EventManager类的RegisterRoutedEvent方法进行注册,该方法第一个参数是路由事件的名称,微软约定路由事件名称要跟路由事件对象的包装器名称一致,而且跟路由事件对象去掉Event后缀的字样也要一致。第二个参数是指路由事件的策略,也就是事件传播的形式,有以下三种枚举:事件

  • RoutingStrategy.Tunnel:隧道式,是指事件从最外层的控件开始路由,直到路由到控件本身,就像一条自上往下的隧道,从window控件一路通到当前触发事件的控件;

  • RoutingStrategy.Bubble:冒泡式,这个跟隧道式相反,它是从触发事件的控件向上传播,直到最上层中止;

  • RoutingStrategy.Direct:直通式,跟原始事件模型同样,不路由,直达事件处理器。

第三个参数是指定该路由事件的事件处理器是什么类型,第四个参数是指定该路由事件对象的宿主类型,第四个参数跟第一个参数共同用于路由事件对象的内部建立使用:构建hash code,肯定路由事件对象惟一性,同依赖属性一致,在一个类中不能注册两个同名的路由事件对象。

    第四段是激发Click路由事件的方法,事件参数就是在此方法中处理,它是路由事件传播之源。

 

【自定义路由事件】

    下面咱们就来根据以上语法,基于ButtonBase建立本身的Click路由事件:

    public class MyRoutedEventArgs : RoutedEventArgs
    {
        public MyRoutedEventArgs(RoutedEvent routedEvent, object source)
            : base(routedEvent, source) { }

        public string RoutedMessage { get; set; }
    }

    public class MyButton : ButtonBase
    {

        public static readonly RoutedEvent MessageEvent =
           EventManager.RegisterRoutedEvent("Message", RoutingStrategy.Bubble,
               typeof(EventHandler<MyRoutedEventArgs>), typeof(MyButton));

        public event RoutedEventHandler Message
        {
            add { this.AddHandler(MessageEvent, value); }
            remove { this.RemoveHandler(MessageEvent, value); }
        }

        protected override void OnClick()
        {
            base.OnClick();

            MyRoutedEventArgs eventArgs =  new MyRoutedEventArgs(MessageEvent, this) 
                                                { RoutedMessage = "自定义路由事件被触发了" };
            this.RaiseEvent(eventArgs);

        } 
    }

 

    上述代码中,我建立了一个MyButton,声明了一个MessageEvent路由事件对象,值得注意的是,RegisterRoutedEvent的第三个参数我用的是:

typeof(EventHandler<MyRoutedEventArgs>)

而非:

typeof(RoutedEventHandler)

由于RoutedEventHandler的参数跟我自定义的事件参数不一致,须要使用EventHandler的泛型版指定个人事件参数类型,下面是RoutedEventHandler的声明:

该参数类型是RoutedEventArgs,而我使用的是自定义的MyRoutedEventArgs类型。

    XAML部分及事件处理器的代码为:

    在外层Grid上设置MyButton的Message事件监听及处理器。

    运行效果以下:

    点击“你好”,弹出MessageBox提示“自定义路由事件被触发了”。

 

下一篇: WPF路由事件