WPF中,控件的事件分为起泡事件和通道事件。起泡事件从接收到事件的元素开始,逐级触发上层元素的同名事件。通道事件从根元素开始,逐级触发下层元素的同名事件,直到接收事件的元素。要关闭这种事件传递,可以在需要中止传递的元素的处理方法中设置EventArgs的Handled属性为true。经过我的实验,控件的通道事件先于起泡事件执行。也就是说如果同时定义了SomeEvent和PreviewSomeEvent事件,并且为SomeEvent和PreviewSomeEvent事件都写了处理方法X_SomeEvent和X_PreviewSomeEvent。那么,只会执行X_PreviewSomeEvent方法。列如:在本例中,不会执行win_MouseDow,btn_MouseDow,lbl_MouseDow方法。除非,删除对应的Preview方法或者在Preview是空方法。
定义一个窗体win,一个按钮btn,一个标签lbl。并设置win内容为btn,btn内容为lbl:
private static Window win = new Window(); private static Button btn = new Button(); private static Label lbl = new Label(); lbl.Content = "Click Me"; btn.Content = lbl; win.Content = btn;
为控件添加鼠标单击事件处理方法:
//为个元素添加鼠标按下事件的冒泡事件处理方法 win.MouseDown += win_MouseDown; btn.MouseDown += btn_MouseDown; lbl.MouseDown += lbl_MouseDown; //为各元素添加鼠标按下事件的通道事件处理方法 win.PreviewMouseDown += new System.Windows.Input.MouseButtonEventHandler(win_PreviewMouseDown); btn.PreviewMouseDown += new System.Windows.Input.MouseButtonEventHandler(btn_PreviewMouseDown); lbl.PreviewMouseDown += new System.Windows.Input.MouseButtonEventHandler(lbl_PreviewMouseDown);
事件处理方法:
//Lable标签的鼠标按下事件的通道事件的处理方法 private static void lbl_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { MessageBox.Show("This is triggered by lbl_PreviewMouseDown"); } //按钮的鼠标按下事件的通道事件处理方法 private static void btn_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { //e.Handled = true; MessageBox.Show("This is triggered by btn_PreviewMouseDown"); } //窗体的鼠标按下事件的通道事件的处理方法 private static void win_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { MessageBox.Show("This is triggered by win_PreviewMouseDown"); } //Lable标签的鼠标按下事件的起泡事件的处理方法 private static void lbl_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { //e.Handled = true; MessageBox.Show("This is triggered by lbl_MouseDown"); } //按钮的鼠标按下事件的起泡事件的处理方法 public static void btn_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { //e.Handled = true; MessageBox.Show("This is triggered by btn_MouseDown"); } //窗体的鼠标按下事件的起泡事件处理方法 private static void win_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { MessageBox.Show("This is triggered by win_MouseDown"); }
运行程序,单击窗体上的按钮。弹出对话框依次显示:
“This is triggered by win_PreviewMouseDown”
“This is triggered by btn_PreviewMouseDown”
“This is triggered by lbl_PreviewMouseDown”
而“This is triggered by btn_MouseDown”等X_MouseDown事件处理方法中要求显示的信息不会显示,注释掉X_PreviewMouseDown事件处理方法后方能显示(X_PreviewMouseDown事件处理方法为空方法时也会显示,不明白),说明通道事件优先于起泡事件。