首页 > 技术文章 > WPF 路由事件

minhost 2017-09-11 19:17 原文

  以前在Windform开发中,大家都熟悉事件,外部事件,如键盘输入、鼠标移动、按动鼠标都由OS系统转换成相应的消息发送到应用程序的消息队列。每个应用程序都有一段相应的程序代码来检索、分发这些消息到对应的窗体,然后由窗体的处理函数来处理。 内部事件通过委托的方式处理。而WPF通过事件路由(event routing)的概念,增强了.net事件模型。事件路由允许源自某个元素的事件由另外一个元素来处理。

  事件路由为在最合适的地方编写紧凑、组织良好的用于处理事件的代码,提供了灵活性。要使用WPF内容模型,事件路由也是必须的。内容模型允许使用许多不同的元素构建简单元素。下面看看我如何定义一个路由事件。

1、定义路由事件

WPF定义路由事件的方式和定义依赖属性特别相似,路由事件也是由静态成员和在静态构造函数中注册,并对window的事件进行了封装,由于所有事件必须基于界面,所以能够添加事件的基础类为System.Windows.UIElement,所以我们定义如下:

class Example : UIElement
{
     //定义事件
     public static readonly RoutedEvent testEvent;
     static Example()
     {
         Example.testEvent = EventManager.RegisterRoutedEvent("Test", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Example));
     }

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

    /// <summary>
     /// 触发事件
     /// </summary>
     public void TestHandler() {
         RoutedEventArgs e = new RoutedEventArgs(Example.testEvent,this);
         this.RaiseEvent(e);
     }
}

 

事件的使用:

public partial class MainWindow : Window
{
     Example example = new Example();
     public MainWindow()
     {
         
         InitializeComponent();
        example.Test += E_Test;
    }

    private void E_Test(object sender, RoutedEventArgs e)
     {
         MessageBox.Show("事件被调用");
     }

    private void Button_Click(object sender, RoutedEventArgs e)
     {
         example.TestHandler();
    }
}

我们点击界面上的案例,则会触发弹出事件被调用,我们分析一下整个过程:

步骤1:申明事件

 public static readonly RoutedEvent testEvent;

步骤2:注册事件

我们使用EventManager类的RegisterRoutedEvent函数进行注册路由事件,如下:

public static RoutedEvent RegisterRoutedEvent( string name, RoutingStrategy routingStrategy, Type handlerType, Type ownerType )

name:路由事件的名称,该名称在所有者类型中必须是唯一的,并且不能为空或者null.

RoutingStrategy:枚举当前事件的策略,三个选项

  • Bubble:路由事件使用冒泡策略,以便事件实例通过树向上路由(从事件元素到根)。
  • Direct:路由事件不通过元素树路由,但支持其他路由的事件功能,例如类处理 EventTrigger 或 EventSetter。
  • Tunnel:路由事件使用隧道策略,以便事件实例通过树向下路由(从根到源元素)。

handlerType:事件处理程序的类型

ownerType:事件的拥有者类型

路由事件通过RaiseEvent函数触发,RaiseEvent函数的申明如下:

RoutedEventArgs e = new RoutedEventArgs(Example.testEvent,this);
this.RaiseEvent(e);

 

推荐阅读