(一)什么时路由事件
功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件。
实现定义:路由事件是一个 CLR 事件,可以由 RoutedEvent 类的实例提供支持并由 Windows Presentation Foundation (WPF) 事件系统来处理
(二)路由事件的划分
(1)冒泡:针对事件源调用事件处理程序。路由事件随后会路由到后续的父元素,直到到达元素树的根。
(2)隧道:最初将在元素树的根处调用事件处理程序。随后,路由事件将朝着路由事件的源节点元素(即引发路由事件的元素)方向,沿路由线路传播到后续的子元素。
(3)直接:只有源元素本身才有机会调用处理程序以进行响应。这与 Windows Forms用于事件的“路由”相似。但是,与标准 CLR 事件不同的是,直接路由事件支持类处理而且可以由 EventSetter 和 EventTrigger 使用。
(三)e.Handled=true“已处理”
如果将 Handled 设置为 true,以此将事件标记为“已处理”,则将“停止”隧道路由或冒泡路由,同时,类处理程序在某个路由点处理的所有事件的路由也将“停止”。
(四)下面列子事件执行循序(操作都是点击TextBlock)
(1)当为冒泡事件时:TextBlock-->Grid-->Window
(2)当为隧道事件时:Window-->Grid-->TextBlock
关于e.Handled=true在列子中的应用理解:e.Handled==true放在哪个事件中执行后,哪个事件之后的路由事件不在执行。
(五)代码
(1)UI代码
1 <Window x:Class="WpfEvent.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" x:Name="window" > 5 <Grid Width="300" Height="200" x:Name="grid" Background="Red"> 6 <TextBlock x:Name="tbx" Width="100" Height="27" Background="Blue" /> 7 </Grid> 8 </Window>
(2)后台代码
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Windows; 6 using System.Windows.Controls; 7 using System.Windows.Data; 8 using System.Windows.Documents; 9 using System.Windows.Input; 10 using System.Windows.Media; 11 using System.Windows.Media.Imaging; 12 using System.Windows.Navigation; 13 using System.Windows.Shapes; 14 15 namespace WpfEvent 16 { 17 //(一)什么时路由事件 18 //功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件。 19 //实现定义:路由事件是一个 CLR 事件,可以由 RoutedEvent 类的实例提供支持并由 Windows Presentation Foundation (WPF) 事件系统来处理 20 //(二)路由事件的划分 21 //(1)冒泡:针对事件源调用事件处理程序。路由事件随后会路由到后续的父元素,直到到达元素树的根。 22 //(2)隧道:最初将在元素树的根处调用事件处理程序。随后,路由事件将朝着路由事件的源节点元素(即引发路由事件的元素)方向,沿路由线路传播到后续的子元素。 23 //(3)直接:只有源元素本身才有机会调用处理程序以进行响应。这与 Windows Forms用于事件的“路由”相似。但是,与标准 CLR 事件不同的是,直接路由事件支持类处理而且可以由 EventSetter 和 EventTrigger 使用。 24 //(三)e.Handled=true“已处理” 25 //如果将 Handled 设置为 true,以此将事件标记为“已处理”,则将“停止”隧道路由或冒泡路由,同时,类处理程序在某个路由点处理的所有事件的路由也将“停止”。 26 //(四)下面列子事件执行循序(操作都是点击TextBlock) 27 //(1)当为冒泡事件时:TextBlock-->Grid-->Window 28 //(2)当为隧道事件时:Window-->Grid-->TextBlock 29 //关于e.Handled=true在列子中的应用理解:e.Handled==true放在哪个事件中执行后,哪个事件之后的路由事件不在执行。 30 /// <summary> 31 /// MainWindow.xaml 的交互逻辑 32 /// </summary> 33 public partial class MainWindow : Window 34 { 35 public MainWindow() 36 { 37 InitializeComponent(); 38 this.grid.MouseLeftButtonDown += new MouseButtonEventHandler(grid_MouseLeftButtonDown); 39 this.tbx.MouseLeftButtonDown += new MouseButtonEventHandler(tbx_MouseLeftButtonDown); 40 this.MouseLeftButtonDown += new MouseButtonEventHandler(window_MouseLeftButtonDown); 41 42 //this.grid.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(grid_PreviewMouseLeftButtonDown); 43 //this.tbx.PreviewMouseLeftButtonDown+=new MouseButtonEventHandler(tbx_PreviewMouseLeftButtonDown); 44 //this.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(window_PreviewMouseLeftButtonDown); 45 46 } 47 48 49 50 private void grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 51 { 52 MessageBox.Show("我是Grid"); 53 } 54 55 private void window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 56 { 57 MessageBox.Show("我是窗体"); 58 59 } 60 61 private void tbx_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 62 { 63 MessageBox.Show("我是TextBlock"); 64 e.Handled = true; 65 66 } 67 68 69 70 private void window_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 71 { 72 MessageBox.Show("我是窗体"); 73 74 75 } 76 77 private void grid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 78 { 79 MessageBox.Show("我是Grid"); 80 //e.Handled = true; 81 82 } 83 84 private void tbx_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 85 { 86 MessageBox.Show("我是TextBlock"); 87 88 } 89 90 } 91 }