Wpf事件没有冒泡
这是我的XAML:
这是C#代码:
namespace WpfApplication4 { /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { protected int eventCounter = 0; public MainWindow() { InitializeComponent(); } private void somethingClicked(object sender, RoutedEventArgs e) { eventCounter++; String message = "#" + eventCounter.ToString() + ":\r\n" + " Sender: " + sender.ToString() + ":\r\n" + " Source: " + e.Source + ":\r\n" + " Original Source: " + e.OriginalSource; lstEvents.Items.Add(message); e.Handled = (bool) chkhandle.IsChecked; if (e.Handled) lstEvents.Items.Add("Completed"); } }
}
我对此示例有以下问题:1)单击按钮时不会触发MouseUp事件。 2)事件没有冒出来。 单击表单上的某处显示:
Sender:WpfApplication4.MainWindow: Source:WpfApplication4.MainWindow: Original Source: System.Windows.Controls.Border.
如果我理解正确,当单击按钮时,首先它应该在Window级别(现在它执行),然后是Grid,然后堆栈,最后是文本标签。 代码错了还是我对这个概念的理解有缺陷?
The MouseUp event is not fired on clicking the button.
因为第一个fires是Button.Click
的事件,当它工作时,它与事件MouseUp
冲突。 从这里引用:
ButtonBaseinheritance自UIElement,Button也可以访问为UIElement定义的所有鼠标按钮事件。 因为按钮按下按钮会执行某些操作,因此会吞下冒泡事件(例如MouseLeftButtonDown和MouseDown)。 您仍然可以通过为隧道事件添加处理程序来检测这些较低级别的按钮事件(例如,PreviewMouseLeftButtonDown和PreviewMouseDown)。
尝试替换Label
上的Button
,您将获得所需的结果:
-
请尝试处理PreviewMouseDown事件。 你仍然可以从XAML附加它。 在你的处理程序中
-
请在代码中附加事件处理程序。 使用AddHandler的签名
。
private void Window_Loaded(object sender, RoutedEventArgs e) { Grid1.MouseUp += new MouseButtonEventHandler(Grid1_MouseUp); } private void Grid1_MouseUp(object sender, MouseButtonEventArgs e) { MessageBox.Show("Mouseup"); }
微软写了一个非常好的解释路由事件概述
在您的情况下, e.Handled = (bool) chkhandle.IsChecked;
MouseUp
和PreviewMouseUp
事件将发生完全相同的事情e.Handled = (bool) chkhandle.IsChecked;
停止事件的路由。
如果你想调试你可以使用Snoop的事件,它将很好地说明哪些事件发生在哪些对象上以及谁处理它们。
有一个覆盖可用于处理事件,即使它们被标记为已处理。 它要求您通过代码添加处理程序,如下所示:
MainWindow.AddHander(UIElement.MouseUpEvent, new MouseButtonEventHandler(button1_MouseUp), true);
最后一个参数指定是否要接受已经处理的事件。 如果将该处理程序添加到主窗口,您会注意到按钮中的路由MouseUp事件确实冒泡了(但是他们的e.Handled表示它们已经被处理过了)。