用于在TreeView中双击最后一个子项的C#WPF事件

时间:2017-04-04 11:22:04

标签: c# wpf xaml treeview

我有一个WPF TreeView,想要在所有没有Child的TreeViewItem上监听doubleclicks。我的TreeView看起来像这样:

simple tree view

TreeView的内容生成如下:

TreeViewItem tvi = new TreeViewItem();
tvi.Header = groupModel.Name;
treeView.Items.Add(tvi);

foreach(Model m in models) {
    TreeViewItem t = new TreeViewItem();
    t.Header = model.Name;
    tvi.Items.Add(t);
}

在我的XAML文件中,我定义了一个EventSetter,它应该在单击TreeViewItem时触发:

<TreeView x:Name="treeView" BorderThickness="0">
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <EventSetter Event="MouseDoubleClick" Handler="OnTreeItemDoubleClick"/>
        </Style>
    </TreeView.ItemContainerStyle>
</TreeView>

在我的代码背后,我定义了处理程序:

public void OnTreeItemDoubleClick(object sender, EventArgs args)
{
    TreeViewItem tvi = (TreeViewItem)sender;
}

当我双击任何TreeViewItem时,会触发Handler,但每次发送者都是TreeViewItem“Level 1”。我想获得被点击的实际TreeViewItem。我该如何做到这一点?

编辑(暂时解决方法)

我一直在想复杂的方法。我只是在生成TreeViewItem时将Handler附加到MouseDoubleClick事件:

t.MouseDoubleClick += OnTreeItemDoubleClick;

我仍然对所描述问题的解决方案感兴趣,并且想知道为什么路由事件不是由嵌套最多的孩子触发的。

1 个答案:

答案 0 :(得分:2)

我注意到如果你没有使用HierarchicalDataTemplate和数据绑定,而是在代码中添加项目,那么EventSetter仅为树的第一级设置事件。我想知道为什么会这样(我自己还没有找到他的问题的答案)。

解决方法是只在代码中订阅事件(因为您无论如何都要手动添加项目):

TreeViewItem tt = new TreeViewItem();
tt.Header = "some item";
tt.MouseDoubleClick += new MouseButtonEventHandler(OnTreeItemDoubleClick);

注意您在处理程序中使用EventArgs,它应该是MouseButtonEventArgs

此外,由于每个TreeViewItem都位于其父级的可视树中,因此该事件将向下冒泡,因此如果您单击已分配MouseDoubleClick的树叶并且它具有2个父级,则该事件将被召唤3次。只有在您检查OriginalSource

后才能处理它
    public void OnTreeItemDoubleClick(object sender, MouseButtonEventArgs e)
    {
        TreeViewItem clickedItem = TryGetClickedItem(treeView, e);

        if (clickedItem == null || clickedItem!=sender)
            return;
        //e.Handled = true; // if you want to to cancel expanded/collapsed toggle

        Console.WriteLine(clickedItem.Header);
    }

    TreeViewItem TryGetClickedItem(TreeView treeView, MouseButtonEventArgs e)
    {
        var hit = e.OriginalSource as DependencyObject;
        while (hit != null && !(hit is TreeViewItem))
            hit = VisualTreeHelper.GetParent(hit);

        return hit as TreeViewItem;
    }