这个是我第一篇文章在博客园。希望能多认识一些技术牛人多交流和学习。如果本人有哪里不正确,望看客指正。
=======我======是======分=======割=======线=======
如果说我们平时所开发winform程序中使用的event为一个normal event的话,WPF提出了自己的概念——RoutedEvent(路由事件)。根据名字来看,这类事件有一定的传导性。RoutedEvent是一个比较特殊的行为,至少在winform程序中,就我所知,我们可以使用Button.RaisedEvent()去实现这样一个功能。当然,这个不是我这篇blog所讨论的重点。接下来让我们具体看一下RoutedEvent这个特殊的行为。
其实我们在创建winform和WPF项目的时候,我们就会发现一个比较明显的区别在引用的地方,那就WPF里面多了两个比较特殊DLL,分别是:PresentationCore.dll和WindowsBase.dll。
我们可以想象这样一个场景,我们如果在一个winform程序中创建一个ComboBox控件,并同时在这个控件里面创建不同的其他类型的控件。这种情况如何实现呢?让我们来看看WPF程序如果来做到这点。一个典型的WPF程序包含很多元素,无论是XAML里面声明的还是在xaml.cs文件code出来,这些元素都存在一个称为element tree的关系型结构中。而事件路由也正是通过这个结构进行事件的向上传递。通常是使用冒泡的形式向上传递,直至到达element tree的root结点。让我们来看一个简单的例子:
1 <Window x:Class="WpfApplication1.MainWindow"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 Title="MainWindow" Height="350" Width="525">
5
6 <Border Height="50" Width="300" BorderBrush="Gray" BorderThickness="1">
7 <StackPanel Background="LightGray" Orientation="Horizontal" Button.Click="CommonClickHandler">
8 <Button Name="YesButton" Width="Auto" >Yes</Button>
9 <Button Name="NoButton" Width="Auto" >No</Button>
10 </StackPanel>
11 </Border>
12 </Window>
我们会看到这个程序中,有一个StackPanel,并且在其中有两个Button。另外我们注意到StackPanel中有一个Button.Click事件,那么这个事件的作用是什么呢?如果我们点击任何一个Button,会不会出发Click事件呢?(因为Button本身并没有定义任何Click事件)让我们继续看下去。
我们会发现代码中已经有一颗很简单的tree。那么当我们点击了StackPanel中的任何一个Button,它会发现Button本身并没有对Click事件进行处理,所以它会根据冒泡原则向上传递,当到达tree结构中Button的父结点(StackPanel)的时候,它发现了Button.Click事件并进行处理。但是这里有一点需要注意的,对于event,他会继续向上传递到Border,然后离开tree的root结点。
所以我们看到的顺序应该是Button-->StackPanel-->Border-->...
从上面的简单例子,我们可以看出其实RoutedEvent机制非常的强大。那么我们可以用在一些什么场合呢?当然这里只是我自己看了MSDN文档和一些blog后的简单总结:我们可以在root结点定义一个比较普通的处理(比如说:我们一个控件中包含了很多不同的控件,但是他们有些共同的事件,我们可以定义在root结点中);我们还可以通过RoutedEvent创建一些自定义控件(我相信这类控件会比winform的强大);当然还有一些其他的场合我们可以使用路由事件,也欢迎大家补充讨论。
那么下面我们比较一些WPF中的RoutedEvent和winform中的普通CLR event。
1. 我们可以想象一下,如果我们在Button上面添加一张图片,那么根据路由事件规则,当我们点击图片的时候,他同样是可以出发Button.Click事件。但是winform里面很难做到这点。
2. WPF中的事件处理器(handler)的声明比较方便,在于一次声明可以供多个使用。就之前的那个XAML例子,我们可以看一下它的xaml.cs文件的写法:
1 private void CommonClickHandler(object sender, RoutedEventArgs e)
2 {
3 FrameworkElement feSource = e.Source as FrameworkElement;
4 switch (feSource.Name)
5 {
6 case "YesButton":
7 MessageBox.Show("YesButton was clicked");
8 break;
9 case "NoButton":
10 MessageBox.Show("NoButton was clicked");
11 break;
12 }
13 e.Handled = true;
14 }
3. 允许声明static handler。其实这个优点,我想大家应该都非常清楚。RoutedEvent允许通过Class声明一个静态的处理器。那么它就可以在任何非静态的处理器执行之前优先先被执行。其实这个原理和static constructor是一样的。
4. 不需要reflection可以在runtime时候引用event。
下面是我写这篇blog的一些参考文档:
希望对大家有帮助。也希望大家指正和踊跃讨论。