对WPF事件路由的理解

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace RoutedEvenDemo
{
    /// <summary>
    /// 对WPF路由事件的理解
    /// </summary>
    public class RoutedEvenDemoTest:UIElement
    {
        public RoutedEvenDemoTest()
        {
            
        }

        /*
         1、在.net已经支持事件的情况下,为什么WPF还额外提供了对路由事件的支持?
           WPF中,我们可以将一个控件作为另一个控件的子控件,从而呈现丰富的效果。
           例如我们可以在一个Button中包含一个图像。在这种情况下,对图像的点击实际上应该是对按钮的点击。
           正因为如此,我们期望真正触发被点击事件的控件是Button,而不是嵌在其中的图像。
           这正好要求WPF将点击事件沿视觉树依次传递,即路由事件的路由功能。
           除了这些较为明显的优点之外,路由事件还提供了更为丰富的功能。
           首先,路由事件允许软件开发人员通过EventManager.RegisterClassHandler()函数使用由类定义的静态处理程序。
           这个类定义的静态处理程序与类型的静态构造函数有些类似:在路由事件到达路由中的元素实例时,WPF都会首先调用该类处理程序,
           然后再执行该实例所注册的侦听函数。这种控件编写方式在WPF的内部实现中经常使用。
           另外,通过对路由事件进行管理的类型EventManager,我们可以通过函数调用GetRoutedEvents()得到相应的路由事件,
           而不再需要运用反射等较为耗时的方法。
         2、路由事件一般有哪几种路由策略
           a.冒泡;由事件源向上沿视觉树传递一直到根元素。如 MouseDown
           b.直接;只有事件源才有机会响应事件,某个元素引发事件后,不传递到其他元素
           c.隧道;从元素树的根部调用事件处理程序并依次向下深入直到事件源。
                  一般情况下,WPF提供的输入事件都是以隧道/冒泡对实现的。隧道事件常常被称为Preview事件。如 PreviewMouseDown
         3、自定义路由事件     
            创建自定义路由事件大体可以分为三个步骤:

            (1)声明并注册路由事件 所属注册的类必须派生于 静态制度的 RoutedEvent 

            (2)为路由事件添加CLR事件包装 AddHandler 与 RemoveHandler

            (3)创建可以激发路由事件的方法
         */


        public static readonly RoutedEvent testEvent = EventManager.RegisterRoutedEvent("test", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(RoutedEvenDemoTest));

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

        void testevent()
        {
            RaiseEvent(new RoutedEventArgs(testEvent));
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            base.OnKeyUp(e);
            testevent();
        }

        /// <summary>
        /// 声明注册一个为名称为 DemoTest 的路由事件
        /// </summary>
        public static readonly RoutedEvent DemoTestEvent =
                    EventManager.RegisterRoutedEvent("DemoTest", RoutingStrategy.Bubble, typeof(EventHandler<DemoTestRoutedEventArgs>), typeof(RoutedEvenDemoTest));


        /// <summary>
        /// CLR事件包装
        /// </summary>
        public event RoutedEventHandler DemoTest
        {
            add { AddHandler(DemoTestEvent, value); }
            remove { RemoveHandler(DemoTestEvent, value); }
        }


        /// <summary>
        /// 激发路由事件
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonDown(e);
            DemoTestRoutedEventArgs args = new DemoTestRoutedEventArgs(DemoTestEvent, this);
            args.ClickTime = DateTime.Now;
            this.RaiseEvent(args);
        }

        ///// <summary>
        ///// 激发路由事件的方法
        ///// </summary>
        //void DemoEvent()
        //{
        //    RoutedEventArgs args = new RoutedEventArgs(RoutedEvenDemoTest.DemoTestEvent);
        //    RaiseEvent(args);
        //}

    }
    
    /// <summary>
    /// 定义一个事件参数类
    /// </summary>
    public class DemoTestRoutedEventArgs : RoutedEventArgs
    {
        public DemoTestRoutedEventArgs(RoutedEvent routedEvent, object source) 
            : base(routedEvent, source)
        {

        }

        public DateTime ClickTime { get; set; }
    }

    /*
     */

}

 

转载于:https://www.cnblogs.com/demo8/p/3278669.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值