路由事件
可以从功能或实现的角度来理解路由事件。 此处对这两种定义均进行了说明,因为有的用户认为前者更有用,有的用户认为后者更有用。
请思考下面的简单代码:
<Window x:Class="路由事件.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Border BorderBrush="Gray" BorderThickness="1">
<StackPanel>
<Button Name="button1" Content="路由事件示例" Click="button1_Click" />
<Button Name="button2" Content="定义和注册路由事件" Click="button2_Click" />
<Button Name="button3" Content="事件路由政策:WPF中的路由事件传递的线路" Click="button3_Click" />
<Button Name="button4" Content="附加事件" Click="button4_Click" />
</StackPanel>
</Border>
</Window>
此代码如下的内容:
在此简化的元素树中,源Click事件是之一Button元素,而所Button单击的是有机会处理事件的第一个元素。 但是,如果没有处理程序附加到Button处理的事件,则该事件将向上冒泡到Button在元素树中,这是父StackPanel。 可能的事件冒泡到Border,然后会到达元素树 (未显示) 的页面根。
换而言之,此事件路由Click事件:
Button-->StackPanel-->Border-->...
当单击 “路由事件示例” 按钮的时候,Button_Click事件被触发:
private void button1_Click(object sender, RoutedEventArgs e)
{
UnderstandRoutedEvent myUnderstandRoutedEvent = new UnderstandRoutedEvent();
myUnderstandRoutedEvent.Show();
}
myUnderstandRoutedEvent.Show() 显示新窗体
<Window x:Class="路由事件.UnderstandRoutedEvent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="UnderstandRoutedEvent" Height="300" Width="300" Name="Win1"
ButtonBase.Click="button1_Click">
<!--为Window和Grid分别关联ButtonBase的Click事件-->
<Grid Name="Grid" ButtonBase.Click="button1_Click">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBox Name="textBox1" TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" />
<!--在按钮的Parent中添加ButtonBase的Click事件关联-->
<StackPanel Grid.Row="1" Orientation="Horizontal" Name="stk" ButtonBase.Click="button1_Click">
<!--为按钮指定单击事件-->
<Button Height="23" Name="button1" Click="button1_Click">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Image Source="OpenPL.bmp" Name="img"></Image>
<TextBlock Text="点击触发单击事件" Name="txt"></TextBlock>
</StackPanel>
</Button.Content>
</Button>
<Button Name="button2" Click="button1_Click" Margin="10,0,0,0">点击触发单击事件</Button>
</StackPanel>
</Grid>
</Window>
在XAML代码中添加了Name="button1" Click="button1_Click"这个事件处理器,就是监听器,并且事件处理交由button1_Click负责,后台Button_Click代码如下:
private void button1_Click(object sender, RoutedEventArgs e)
{
++i;
StringBuilder eventstr = new StringBuilder();
//获取触发事件的元素
FrameworkElement fe = (FrameworkElement)sender;
//显示触发的次序
eventstr.Append("触发时次序:" + i.ToString() + "\n");
eventstr.Append("触发事件的元素名:");
eventstr.Append(fe.Name);
eventstr.Append("\n");
//获取事件源,也就是是由哪个元素所引发的事件。
FrameworkElement fe2 = (FrameworkElement)e.Source;
eventstr.Append("事件源类型:");
eventstr.Append(e.Source.GetType().ToString());
eventstr.Append("\n");
eventstr.Append(" 名称:");
eventstr.Append(fe2.Name);
eventstr.Append("\n");
//获知事件传递的方法
eventstr.Append("路由策略:");
eventstr.Append(e.RoutedEvent.RoutingStrategy);
eventstr.Append("\n");
textBox1.Text += eventstr.ToString();
}
运行效果如下所示:
RoutedEventArgs属性:
* 1.Source:指定哪个对象引发了事件,对于键盘事件来说,是指具有输入焦点的对象,而对于鼠标事件来说,
* 是指鼠标下面最顶层的,Enable为True的元素。由于路由事件的传递特性,Source的值将与事件实参类
* 的sender形参的值有可能不同。
* 2.OriginalSource:指定哪个对象最初引发了事件,通常与Source属性的值相同,然而在一些情况下OriginalSource
* 可能比Source属性引用的元素更精细。例如,如果单击窗口边缘,Source属性时Window对象,而OriginalSource则是Border
* 对象,最初是Border对象触发了单击事件。通常较少使用OriginalSource属性来获取事件源。
* 3.RouteEvent:可以使用该属性获取当前触发的事件的类型,比如UIElement.MouseUpEvent对象,在使用相同的事件
* 处理器处理不同的事件时非常有用。
* 4.Handled:允许停止冒泡或隧道事件处理。如果将Handled设置为TRUE,事件将不再继续传递,也不会被触发