【问题标题】:wpf treeviewitem mouse double clickwpf treeviewitem 鼠标双击
【发布时间】:2014-11-05 21:59:58
【问题描述】:

我无法识别所选 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 ... 我可以解决这个问题?

【问题讨论】:

    标签: wpf


    【解决方案1】:

    我认为的问题是ItemContainerStyle 仅适用于第一级节点(我认为这是由于TreeView 继承自ItemsControlItemContainerStyle 从那里继承的方式 - 仅适用于到ItemsControl 的基本Items。无论如何,我要去一个......)

    您可以修复它,而不是将样式分配给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 事件(微软显然使用它来触发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());
        }
    }
    

    但是,由于 Preview 事件向下隧道,不幸的是它会在包含项目上触发一次,而不是在包含项目上,所以我们回到第 1 格。我们可以在这里查看args.OriginalSource,但我们是基本上已经到了建议采用不同解决方案的阶段:

    单独选择

    另一种选择是在其双击事件上为整个TreeView 添加一个事件侦听器,然后简单地查找TreeViewItemOriginalSource 所在的位置。 (如果您想处理它并阻止它传播/引起其他影响,您需要改为挂钩到上面的 PreviewMouseLeftButtonDown 事件)。

    为此,您可以使用MouseButtonEventArgs args 并考虑args.OriginalSource(这是您单击的可视化树上最顶部的元素),然后您会遇到一些情况:要么它不在任何@ 内987654349@,或者它本身就是您需要的TreeViewItem,或者第三种可能性是 OriginalSource 是您需要的TreeViewItem 内部某处的元素(这是最可能的情况 - 从测试中,您通常单击TextBlock 包含在 TreeViewItem) 中,在这种情况下,您可以递归地查找父级,直到找到类型为 TreeViewItem 的第一个父级。 (您可以使用VisualTreeHelper GetParent 方法来做到这一点。)

    基本上,上述算法可以总结为递归检查当前项目以查看它是否属于TreeViewItemTreeView 类型,否则您将当前项目设为其父项并递归...如果您以@ 结束987654359@,你有需要的项目,否则如果你在项目外点击,你最终会在TreeView

    PS:由于我不会写VB,我认为解释上述算法可能比尝试编写它更好 - 但我希望上述解释仍然对你有用:)

    【讨论】:

    • 您好,感谢您的帮助,可以工作,但是因为我的控件样式被更改(样式元素树视图丢失)?
    • 不太明白你的意思? (例如(样式元素树视图丢失)?)。如果您在上面发布您的风格和您想要的效果,我可能会提供帮助:)
    • 我目前正在使用 MahApps.Metro,这里我有一张没有点击事件的图片,还有另一张带有样式更改产品的点击事件图片:照片 1 (i.imgur.com/pedXtEI.jpg) 和照片 2 (i.imgur.com/hvwP7uV.jpg)。
    • 啊,好吧,对不起!问题是我们无意中在本地覆盖了您的自定义样式,但我们希望在此基础上进行构建。所以尝试将定义样式的行更改为:&lt;Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}"&gt; 并告诉我这是怎么回事。
    • 作品 ¡¡¡ ...谢谢大家 =D .. 我会为你献上我的圣洁蜡烛 = D
    猜你喜欢
    • 1970-01-01
    • 2019-02-09
    • 2010-12-10
    • 2011-04-16
    • 1970-01-01
    • 2012-05-18
    • 1970-01-01
    • 2017-07-12
    • 1970-01-01
    相关资源
    最近更新 更多