何时隧道和冒泡事件在WPF中有用?

我理解冒泡和隧道是如何工作的。 但是,我对使用它们很困惑。 原因如下:

我想处理鼠标点击事件。 要冒泡它,有MouseDown并且为了隧道它,有PreviewMouseDown 。 但是, MouseDown并不一定意味着用户单击了该控件。 可能是用户按下按钮并离开它以取消点击。 如果没有点击按钮,我不想改变任何东西。

所以我的问题是,Bubbling / Tunneling策略有用吗?

如果事件列在RoutedEventArgs ,那么它就是路由事件。 路由事件支持Bubble,Tunnel或Direct的RoutingStrategy。 我们来看看Button.Click的事件处理程序:

 private void Grid_Click(object sender, RoutedEventArgs e) { MessageBox.Show("Button Test clicked!"); } 

指定了RoutedEventArgs ,因此它是路由事件。 因为未在名称中指定预览 ,因此这个Bubble事件。 这可以通过以下方式certificate:

    

当您单击TestButton ,事件将超出Grid ,并显示一条消息:

按钮测试点击!

Usefulness of Bubbling/Tunneling strategies

Tunneling

许多标准控件都会监听事件,例如KeyDownMouseDown等。例如 – DataGrid控件。 我想按下回车键,该function被称为添加记录。 但DataGrid已经有KeyDown事件,因此不会引发事件。 所以你必须在Tunnel事件中做你的逻辑 – PreviewKeyDown ,它将在KeyDown事件之前工作。 这同样适用于RichTextBoxControl

Bubbling

有时,您需要一个特定事件的全局处理程序,因此它适用于VisualTree中的所有控件。 当然,直接的事件你不能这样做。 因此在舞台上出现Bubbling事件。

另一个原因是WPF的意识形态。 此Button可以包含任何内容: Image ,另一个Button等:

在此处输入图像描述

用户可以单击按钮中的TextBlock/Image 。 我们怎么知道点击是在Button ? 这是正确的,在Bubbling活动的帮助下。

有关更多信息,请参阅:

了解WPF中的路由事件和命令

Edit

我改变了Click处理程序:

 private void Grid_Click(object sender, RoutedEventArgs e) { String message = "#" + eventCounter.ToString() + ":\r\n" + " Sender: " + sender.ToString() + ":\r\n" + " Source: " + e.Source + ":\r\n" + " Original Source: " + e.OriginalSource; lstEvents.Items.Add(message); } 

单击Button结果:

在此处输入图像描述

嗨,虽然你可以在网上获得一些好的文章,但我仍然会尝试回答这个问题。

假设你给一个按钮一个非常简单的外观,由一个Rectangle组成,并提供一个简单的文本作为内容即使有这样的基本视觉效果,仍然有两个元素存在:文本和矩形。按钮应响应一个鼠标单击鼠标是否在文本或矩形上。 在标准的.NET事件处理模型中,这意味着为两个元素注册MouseLeftButtonUp事件处理程序。

利用WPF的内容模型时,这个问题会变得更糟。 Button不限于将纯文本作为标题 – 它可以包含任何对象作为内容。 下面的xaml不是特别雄心勃勃,但即使这有六个可见元素:黄色轮廓圆,眼睛的两个点,嘴的曲线,文本和按钮背景本身。 为每个元素附加事件处理程序将是乏味且低效的。 使用MouseDown我们必须在这段代码中添加8个MouseDownEvents。

  

WPF使用RoutedEvents Bubble / Tunnel / Normal ,它比普通事件更彻底。 WPF不再仅仅调用附加到引发事件的元素的处理程序,而是遍历用户界面元素树,调用从发起元素到任何节点的路由事件的所有处理程序,直到用户界面树的根。

正如你所说,你知道冒泡/隧道的概念,所以不要进入那个。 但这就是这些事件的目的,即它们会让你知道控件上的鼠标按钮是否为Down或Up或它们的子节点。事件正常。对于你的场景,你应该使用按钮的Click事件来判断是否鼠标按下按钮本身。

谢谢