我在识别所选TreeViewItem的名称时遇到问题;我在树视图中有以下结构:
+ Module 1 (name k1)
- Sub Module 1 (name s1)
+ Module 2 (name k2)
- Sub Module 2 (name s2)
+ Module 3 Name (k3)
- Sub Module 3 (name s3)
- Sub Module 4 (name s4)
我是xaml:
<TreeView x:Name="treview_Menu">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<EventSetter Event="MouseDoubleClick" Handler="OnItemMouseDoubleClick" />
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
在代码中我有这个:
Private Sub OnItemMouseDoubleClick(sender As Object, args As MouseButtonEventArgs)
MsgBox(sender.name)
End Sub
在上面的代码中总是返回顶级节点的名称,例如,如果我双击sub_module 3 o sub_module 4总是返回Module_3的名称,同样的情况发生在sub_module 1和sub_module 2 ...因为我可以解决这个问题?
答案 0 :(得分:5)
我认为问题是ItemContainerStyle
仅适用于第一级节点(我相信这是TreeView
继承自ItemsControl
和ItemContainerStyle
的方式所致继承自那里 - 只适用于Items
的基本ItemsControl
。无论如何,我要去一个......)
您可以修改它,而不是将样式分配给ItemContainerStyle
,只需将其移至Resources
,就像这样:
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}">
<EventSetter Event="MouseDoubleClick" Handler="OnItemMouseDoubleClick"/>
</Style>
</TreeView.Resources>
因为这会为每个 TreeViewItem添加一个触发器 - 不幸的是,它们会像这样嵌套:
<TreeViewItem Header="Module 1">
<TreeViewItem Header="Sub Module 1"/>
</TreeViewItem>
<TreeViewItem Header="Module 2">
<TreeViewItem Header="Sub Module 1"/>
<TreeViewItem Header="Sub Module 2"/>
</TreeViewItem>
因此,根据您实际使用代码的内容,可能是事件触发两者外部和内部模块的问题。
在ClickEvent
中处理此问题的常用方法是在代码中将args.Handled
设置为True
,这会将事件'冒泡'停止到更高级别。但不幸的是,由于它们的触发方式,这对MouseDoubleClick
事件无效。 (很好的一个微软...... xD)
可能的答案是:https://stackoverflow.com/a/6326181/3940783
基本上,我们不使用MouseDoubleClick
事件,而是使用PreviewMouseLeftButtonDown
事件(Microsoft使用该事件显然触发MouseDoubleClick
事件)。无论如何,我们可以这样开火:
(请原谅C#,我试图从wpf的角度回答这个问题,但我不知道等效的VB代码)
OnItemPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
if (e.ClickCount == 2) {
e.Handled = true;
var treeViewItem = sender as TreeViewItem;
MessageBox.Show(treeViewItem.Header.ToString());
}
}
然而,因为预览事件隧道向下,它不幸在包含的项目上触发一次,而不是包含的项目,所以我们回到了正方形1.我们可以在这里查看args.OriginalSource
但是我们我基本上已经到了建议采用不同解决方案的阶段:
另一种选择是在其双击事件中向整个TreeView
添加一个事件监听器,然后只需查找其TreeViewItem
所在的OriginalSource
。 (如果你想处理它并阻止它传播/引起其他影响,你需要改为上面的PreviewMouseLeftButtonDown
事件,而不是如上所述。)
为此,您可以选择MouseButtonEventArgs args
并考虑args.OriginalSource
(这是您点击的可视树上最顶层的元素),然后您会遇到一些情况:要么是根本不在任何TreeViewItem
内,或者它本身就是您需要的TreeViewItem
,或者第三种可能性是OriginalSource是您需要的TreeViewItem
内的某个元素(这是最多的)可能的情况 - 从测试开始,您通常会点击TextBlock
中包含的TreeViewItem
,在这种情况下,您可以递归查找父项,直到您点击TreeViewItem
类型的第一个父项。 (您可以使用VisualTreeHelper
GetParent
方法执行此操作。)
基本上,上述算法可以概括为只是递归检查当前项目以查看它是TreeViewItem
类型还是TreeView
否则你将当前项目作为其父项并递归...如果你以TreeViewItem
结束,你有所需的项目,否则如果你点击一个项目,你将最终到TreeView
。