路由事件实际上分两类:冒泡事件(浮升事件)和预览事件(隧道事件)。

冒泡事件是WPF路由事件中最为常见,它表示事件从源元素扩散(传播)到可视树,直到它被处理或到达元素。

这样您就可以针对源元素的上方层级对象处理事件。

例如,您可向嵌入的 Grid 元素附加一个 Button.Click 处理程序,而不是直接将其附加到按钮本身。

气泡事件有指示其操作的名称(例如,MouseDown)。

 

示例:

先建立一个WPF项目,向XAML中的Grid布局中编写以下代码

 

<Border Height="50" Width="250" BorderBrush="Gray" BorderThickness="3">

        <StackPanel Background="LightBlue" Orientation="Horizontal" MouseUp="StackPanel_MouseUp">

<TextBlock Name="YesTB" Width="70" MouseUp="YesTB_MouseUp" Background="LightCoral" Text="Yes" FontSize="25" />

        </StackPanel>

 </Border>

     

分别向StackPanel,TextBlock中嵌入一个鼠标按下事件(MouseUp),在后台分别显示一个不同的提示框;

代码如下:

//冒泡事件

private void StackPanel_MouseUp(object sender, MouseButtonEventArgs e)

{

      MessageBox.Show("Panel", "提示");

}

private void StackPanel_PreviewMouseUp(object sender, MouseButtonEventArgs e)

  {

       MessageBox.Show("PreviewButton", "提示");

  }

 

隧道事件采用另一种方式,从根元素开始,向下遍历元素树,直到被处理或到达事件的源元素。

这样上游 元素就可以在事件到达源元素之前先行截取并进行处理。

根据命名惯例,隧道事件带有前缀 Preview(例如 PreviewMouseDown)。

 

  示例:

  在上个页面布局中再嵌入一个Border内容控件

//隧道事件

         <Border Height="50" Width="250" Margin="0,200,0,0" BorderBrush="Bisque" BorderThickness="3">

<StackPanel Background="AliceBlue" Orientation="Horizontal" PreviewMouseUp="StackPanel_PreviewMouseUp">

<TextBlock Name="NoTB"  Width="70" PreviewMouseUp="NoTB_PreviewMouseUp" Background="Aqua" Text="No" FontSize="25"/>

         </StackPanel>

    </Border>

同样在上面代码中嵌入两个隧道鼠标按下事件

 

后台代码:

private void StackPanel_PreviewMouseUp(object sender, MouseButtonEventArgs e)

  {

        MessageBox.Show("PreviewButton", "提示");

  }

  private void NoTB_PreviewMouseUp(object sender, MouseButtonEventArgs e)

  {

        MessageBox.Show("PreviewText", "提示");

}

 

好了,我们运行来看下样式,如下图:

WPF路由事件

 

从上而下来看,上面为冒泡事件,点击Yes会先弹出TextBlock上的提示框内容,确定后继而在弹出StackPanel上的提示框内容。

下面为隧道事件,与冒泡事件提示却恰恰相反,点击No会先弹出StackPanel上的提示框内容,点击确定后在弹出TextBlock上的提示框内容。

有一点要注意:源元素指定的是那种事件,而其触发的也只会是同一种事件。

那我们不想一层一层往上(或往下)触发那该怎么办呢?

所以有一个中断事件路由的属性, RoutedEventArgs 定义了一个采用布尔 值的 Handled 属性。 

Handled 属性的目的在于,允许路由中的任何事件处理程序通过将 Handled 的值设置为 true 来将路由事件标记为“已处理”。

我们只需在后台代码中添加一句代码就可以

e.Handled = true;

这样事件就不会一层层的继续触发了。

相关文章: