何时隧道和冒泡事件在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
许多标准控件都会监听事件,例如KeyDown
, MouseDown
等。例如 – 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
事件来判断是否鼠标按下按钮本身。
谢谢