处理的 TreeView.SelectedItemChanged 事件仍然冒泡
我有一个 TreeView 通过 HierarchicalDataTemplate 绑定到由多个不同类组成的层次结构。当选择树中的某个项目时,SelectedItemChanged
事件当然会愉快地通过父项向上冒泡,这是理所当然的。它不应该做但仍然做的是,在我将 e.Handled 设置为 true 后继续冒泡。
该事件仍将在父项上触发,并且 RoutedPropertyChangedEventArgs 看起来与所选的父项完全相同;甚至 OriginalSource
属性也会指向父项,而不是最初选择的项。 e.Handled
当然是false
。
这里提出了几乎相同的问题,但我不是使用 EventAggregator
或 CAL,并找到了解决方法 此处没有多大帮助,因为我并不是专门在鼠标事件之后。
有什么方法可以精确地获取实际选择的项目或强制停止冒泡的疯狂(而不诉诸使用我能想到的全局变量的非常暴力和不道德的黑客行为)?
感谢您的任何见解。
I have a TreeView bound to a hierarchy consisting of several different classes via HierarchicalDataTemplate
s. When an item in the tree is selected, the SelectedItemChanged
event of course happily bubbles upwards through the parent items, as it should. What it should not do, but still does, is happily keeping on bubbling after I set e.Handled
to true
.
The event will still fire on the parent item, and the RoutedPropertyChangedEventArgs
will look exactly like it was the parent item that was selected; even the OriginalSource
property will point to the parent item, not the one that was originally selected. e.Handled
will of course be false
.
Pretty much the same question was asked here, but I'm not using EventAggregator
or CAL, and the workaround found here doesn't help much because I am not specifically after a mouse event.
Is there any way to precisely get the item that was actually selected or to forcefully stop the bubbling madness (without resorting to a very violent and unethical hack using global variables that I can think of)?
Thanks for any insights.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
读完 Rick 的回答后,我与一位同事交谈,结果发现他以前也遇到过同样的问题。我在我的应用程序中尝试了各种方法(发现:TreeViewItem.Selected 事件的行为完全相同)和一个测试项目,并发现在测试应用程序中事件的触发与人们的预期完全一致。因此,环境中一定存在显着差异(XAML 和 ViewModel 类几乎相同),从而导致了这种行为差异 - 而罪魁祸首似乎是 COM,它恰好在 COM 应用程序中托管 WPF 控件。
我同事的应用程序是使用 VSTO 的 Word 扩展,而我的应用程序是 Visual Studio 2010 的 VSPackage - 并且 Word 和 VS2010 大部分仍然是本机代码。另一方面,我的测试应用程序当然是一个小型的普通 WPF 项目。我添加了一个带有 ElementHost 的 WinForms 表单,该表单又托管了一个带有 TreeView 的 UserControl,但它仍然按其应有的方式工作,所以对我来说,它确实看起来像主机 COM 应用程序以某种方式干扰了在TreeView 和 TreeViewItems。
幸运的是,我的同事找到/谷歌搜索了一个暂时可行的解决方案 - 在完成对事件的实际反应后,在事件处理程序方法的末尾,再次将 TreeViewItem 设置为选定状态并聚焦它:
我们不明白为什么,但这将阻止错误地重新选择项目(这显然不是 WPF 意义上的冒泡事件)。
再次感谢 Rick 推动我将 TreeView 和 TreeViewItem 事件分开。
After reading Rick's answer, I talked to a co-worker who it turned out had had the same problem before. I tried various things in my application (finding: the TreeViewItem.Selected event behaves exactly the same wrong way) and a test project and found that in the test app the events were firing exactly as one would expect it. So there had to be a significant difference in the surroundings (the XAML and ViewModel classes were nearly identical) that led to this difference in behavior - and the culprit looks to be COM, precisely hosting the WPF controls in a COM application.
My colleague's application is a Word extension using VSTO, while mine is a VSPackage for Visual Studio 2010 - and both Word and VS2010 are still native code for the most part. My test application, on the other hand, is of course a small plain WPF project. I added a WinForms form with an ElementHost to it that in turn hosted a UserControl with a TreeView, but that still worked as it should, so to me it really looks like the host COM application is in some way interfering with the events raised on the TreeView and TreeViewItems.
Luckily, my colleague found/googled a solution that will do for the time being - after you're done with the actual reaction to the event, at the end of the event handler method, again set the TreeViewItem as selected and focus it:
We don't understand why, but this will stop the items from being wrongfully re-selected (this is obviously not really a bubbling event in the WPF sense).
Thanks again to Rick for his nudge towards keeping TreeView and TreeViewItem events separate in my mind.
您的问题让我很困惑,因为
SelectedItemChanged
事件是TreeView
事件,而不是TreeViewItem
事件。 “嘿伙计,我的活动与你的活动相差甚远!”当所选项目发生更改时,
TreeView
会在自身、TreeView
和 上引发SelectedItemChanged
事件如果未处理,它将开始向上冒泡到页面的根元素。当您需要证据时,编写一个小型测试程序会有所帮助。
这是一个包含在
Grid
中的小TreeView
:这是测试的代码隐藏:
运行它并单击第一项会生成此调试输出
:事件在
TreeView
本身上引发,并将e.Handled
设置为true
可防止Grid
接收该事件。将该行注释掉,它就会冒泡到Grid
。但在任何情况下,
TreeViewItem
都不会调用SelectedItemChanged
处理程序。当事情没有按照您的预期运行时,请尝试使用小型测试程序。做实验并找到问题的核心要容易得多!
Your question mystifies me because the
SelectedItemChanged
event is aTreeView
event, not aTreeViewItem
event. "Hey man, my event was nowhere near your event!"When the selected item changes, the
TreeView
raises theSelectedItemChanged
event on itself, theTreeView
, and if unhandled it begins bubbling up towards the root element of the page.Writing a small test program helps when you want proof.
Here's a small
TreeView
contained in aGrid
:and here's the code-behind for the test:
and running it and clicking the first item produces this debug output:
which shows that the event is raised on the
TreeView
itself and settinge.Handled
totrue
prevents theGrid
from receiving the event. Comment that line out and it does bubble up to theGrid
.But in no case does the
TreeViewItem
ever have theSelectedItemChanged
handler called.Try using small test programs when things are not behaving as you think they should. It's much easier to do experiments and get to the heart of the problem!