路由事件
路由事件与直接事件的区别
- 直接事件激发时,发送者将消息通过事件订阅交给事件响应者,事件响应者用其事件处理器方法对事件的发生做出响应。
- 路由事件的事件拥有者和事件响应者没有直接的显示的订阅关系,事件的拥有者只负责激发事件,事件将由谁响应它不知道。事件的响应者安装有事件侦听器,针对某一类事件进行侦听,当有此类事件传递至此时事件响应者就使用事件处理器来响应事件,并决定事件是否可以继续传播。
使用WPF内置路由事件
<Grid Name="gridRoot" Background="Lime" ButtonBase.Click="ButtonClicked">
<Grid Margin="10" Name="gridA" Background="Blue">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Canvas Name="canvasLeft" Grid.Column="0" Background="Red" Margin="10">
<Button Name="buttonLeft" Content="Left" Width="40" Height="100" Margin="10"/>
</Canvas>
<Canvas Name="canvasRight" Grid.Column="1" Background="Yellow" Margin="10">
<Button Name="buttonRight" Content="Right" Width="40" Height="100" Margin="10"/>
</Canvas>
</Grid>
</Grid>
c#代码
private void ButtonClicked(object sender, RoutedEventArgs e)
{
MessageBox.Show((e.OriginalSource as FrameworkElement).Name);
}
结果:
创建路由事件
主要分为三个步骤:
- 声明并注册路由事件
- 为路由事件添加CLR事件包装
- 创建可以激发路由事件的方法
下面利用ButtonBase中的代码进行分析:
//声明注册路由事件
public static readonly RoutedEvent ClickEvent = EventManager.RegisterRoutedEvent(
"Click" //路由事件的名称,string类型
/*
路由事件的策略:
1. Bubble 冒泡式,向激发着的上层传递
2. Tunnel 隧道式,事件路由方向由UI树根向事件激发控件移动。
3. Direct 直达式,模仿直达事件。
*/
,RoutingStrategy.Bubble
,typeof(RoutedEvent) //指定事件处理器的类型。事件处理器的返回值类型和参数列表必须与此参数指定的委托一致
,typeof(Buttonbase) //指定路由事件的宿主(拥有者)是哪一个类型
)
- 注意上面第一个参数和第四个参数共同参与底层的算法,且产生这个路由事件的Hash Code并注册到程序的路由事件列表中。
//为路由事件添加CLR事件包装器
pulic event RoutedEventHandler Click
{
add {this.AddHandler(ClickEvent,value);} //+=
remove{this.RemoveHandler(ClickEvent,value);} //-=
}
protected virtual void OnClick()
{
//创建让事件携带的消息,并把它与路由事件关联
RoutedEventArgs newEvent = new RoutedEventArgs(ButtonBase.ClickEvent,this);
//发送事件
this.RaiseEvent(newEvent);
}