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; } } /* */ }