Dee*_*tan 18 c# wpf mouseevent routed-events
我的场景,简化:我有一个包含Employees行的ListView,在每个Employee行中,有一些按钮"Increase"和"Decrease"调整他的工资.
假设在我的程序中,双击Employee行意味着"解雇此人".
该问题是,当我点击"增加"迅速,这将触发对ListViewItem的双击事件.当然,当我只是增加薪水时,我不想解雇员工.
根据所有其他事件的工作原理,我希望能够通过设置Handled=true事件来解决这个问题.但是,这不起作用.在我看来,WPF生成两个独立的,完全未链接的双击事件.
以下是重现我的问题的最小示例.可见组件:
<ListView>
<ListViewItem MouseDoubleClick="ListViewItem_MouseDoubleClick">
<Button MouseDoubleClick="Button_MouseDoubleClick"/>
</ListViewItem>
</ListView>
Run Code Online (Sandbox Code Playgroud)
和处理程序代码:
private void Button_MouseDoubleClick(object s, MouseButtonEventArgs e) {
if (!e.Handled) MessageBox.Show("Button got unhandled doubleclick.");
e.Handled = true;
}
private void ListViewItem_MouseDoubleClick(object s, MouseButtonEventArgs e) {
if (!e.Handled) MessageBox.Show("ListViewItem got unhandled doubleclick.");
e.Handled = true;
}
Run Code Online (Sandbox Code Playgroud)
启动此程序并双击列出的按钮后,两个消息框按顺序显示.(此外,此后按钮会卡在向下位置.)
作为一个"修复",我可以在ListViewItem处理程序上检查附加到事件的可视树,并检查"那里有一个按钮",从而丢弃事件,但这是最后的手段.我想在编码这样一个kludge之前至少理解这个问题.
有谁知道为什么 WPF会这样做,以及一种优雅的惯用方法来避免这个问题?
Ken*_*art 10
我想你会发现MouseDoubleClick事件是事件的抽象MouseDown.也就是说,如果两个MouseDown事件以足够快的速度连续发生,那么MouseDoubleClick事件也将被提升.无论是Button和ListViewItem似乎有这样的逻辑,所以这可以解释为什么你看到两个不同的MouseDoubleClick事件.
根据MSDN:
尽管此路由事件似乎遵循通过元素树的冒泡路径,但它实际上是每个UIElement沿元素树引发的直接路由事件.如果在MouseDoubleClick事件处理程序中将Handled属性设置为true,则沿着路径的后续MouseDoubleClick事件将在Handled设置为false的情况下发生.
你可以尝试处理MouseDown上Button和设置,要处理,使得它不会传播到ListViewItem.
希望我能亲自验证这一点,但此刻我还没有.NET.
MouseDoubleClick 的MSDN文档确实提供了有关如何防止MouseDoubleClick事件冒泡的建议:
想要处理鼠标双击的控件作者应该在ClickCount等于2时使用MouseLeftButtonDown事件.这将导致Handled的状态在元素树中的另一个元素处理事件的情况下适当地传播.
因此,如果ClickCount为2,您可以处理MouseLeftButtonDown事件并将hanged设置为true.但是这在Buttons上失败了,因为它们已经处理了MouseLeftButtonDown并且没有引发该事件.
但仍有PreviewMouseLeftButtonDown事件.当ClickCount等于2时,在按钮上使用它将handle设置为true:
private void Button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
if (e.ClickCount == 2)
e.Handled = true;
}
Run Code Online (Sandbox Code Playgroud)