路由事件是由公共的静态RoutedEvent成员加上一个约定的Event后缀名构成的。路由事件的注册:它会定义一个普通的.NET事件或者一个事件包装器(event wrapper),这样可以保证在过程式代码中使用起来更加熟悉,并且可以在XAML中用事件特性语法(event attribute syntax)添加一个事件处理程序。事件包装器在访问器中只能调用AddHandler和RemoveHandler,而不应该做其他事情。
路由策略(优先级递减):
所谓路由策略就是事件触发遍历整棵元素树的方式,这些策略由RoutingStrategy枚举值提供。
1、Tunneling(管道传递)——事件首先在根元素上被触发,然后从每一个元素向下沿着树传递,直到到达源元素为止(或者直到处理程序把事件标记为已处理为止。它们的名字中都有一个Preview前缀。例如,PreviewMouseMove
2、Bubbling(冒泡)——事件首先在源元素上被触发,然后从每一个元素向上沿着树传递,直到到达根元素为止(或者直到处理程序把事件标记为已处理为止)。
3、Direct(直接)——事件仅在源元素上触发。这与普通.NET事件的行为相同,不同的是这样的事件仍然会参与一些路由事件的特定机制,如事件触发器。
事件处理程序:
路由事件的事件处理程序有一个签名,它与通用.NET事件处理程序的模式匹配:第一个参数是一个System.Object对象,名为sender,第二个参数(一般命名为e)是一个派生自System.EventArgs的类。传递给事件处理程序的sender参数就是该处理程序被添加到的元素。参数e是RoutedEventArgs的一个实例(或者派生自RoutedEventArgs),RoutedEventArgs是EventArgs的一个子类,它提供了4个有用的属性:
1、Source——逻辑树中一开始触发该事件的元素。
2、OriginalSource——可视树中一开始触发该事件的元素(例如,TextBlock或者标准Button元素的ButtonChrome子元素)。
3、Handled——布尔值,设置为true表示标记事件为已处理,这就是用于停止Tunneling或Bubbling的标记。
4、RoutedEvent——真正的路由事件对象(如Button.ClickEvent),当一个事件处理程序同时被用于多个路由事件时,它可以有效地识别被触发的事件。
例:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="About WPF Unleashed" SizeToContent="WidthAndHeight"
Background="OrangeRed"
x:Class="AboutDialog" MouseRightButtonDown="AboutDialog_MouseRightButtonDown">
在Window根元素上添加了一个事件处理程序AboutDialog_MouseRightButtonDown,对应代码:
void AboutDialog_MouseRightButtonDown(object sender, MouseEventArgs e)
{
// 显示这个事件的信息
this.Title = "Source = " + e.Source.GetType().Name + ", OriginalSource = " +
e.OriginalSource.GetType().Name + " @ " + e.Timestamp;
// 该示例中,所有可能从Control派生而来的源
Control source = e.Source as Control;
// 调整源控件的边框宽度
if (source.BorderThickness != new Thickness(2))
{
source.BorderThickness = new Thickness(2);
source.BorderBrush = Brushes.Yellow;
}
else
{
source.BorderThickness = new Thickness(0);
}
}
中,然后会在逻辑树中的被右击的这个元素周围添加(最终会移除)一个较厚的黑边框