获取 WPF 中选定节点的父 TreeViewItem

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26624982/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 12:39:46  来源:igfitidea点击:

Get parent TreeViewItem of a selected node in WPF

c#wpftreeviewwpf-controlstreeviewitem

提问by nan

I want the parent of a node that is selected as TreeViewItem

我想要一个被选为 TreeViewItem 的节点的父节点

I have a Person class with 2 fields. Name(String) and Children(List of string)

我有一个包含 2 个字段的 Person 类。名称(字符串)和儿童(字符串列表)

This is my xaml code

这是我的 xaml 代码

<Grid x:Name="gridView" Margin="10">
    <TreeView Name="treeView1" TreeViewItem.Selected="TreeViewItem_OnItemSelected" ItemsSource="{Binding}">
        <TreeView.ItemContainerStyle>
            <Style TargetType="{x:Type TreeViewItem}">
                <Setter Property="IsSelected" Value="{Binding IsSelected, Source=Check, Mode=TwoWay}" />
            </Style>
        </TreeView.ItemContainerStyle>
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type loc:Person}" ItemsSource="{Binding Children}" >
                <TextBlock Text="{Binding Name}" />
            </HierarchicalDataTemplate>
        </TreeView.Resources>
    </TreeView>
</Grid>

this is my code behind. I set the item source to a list of Person objects.

这是我背后的代码。我将项目源设置为 Person 对象列表。

void set()
{
    if (treeView1.Items.IndexOf(treeView1.SelectedItem) != -1)
    {
        //is a parent 
        //returns -1 for children
        Person selected = (Person)treeView1.SelectedItem;
        int index = search(selected);
        TreeViewItem parent = treeView1.Tag as TreeViewItem;
        setSelected(parent,index);
    }
    else
    {
        //is a child
        TreeViewItem child = treeView1.Tag as TreeViewItem; //returns the selected node
        TreeViewItem parent = child.Parent as TreeViewItem; //returns null
    }
}
private void TreeViewItem_OnItemSelected(object sender, RoutedEventArgs e)
{
    treeView1.Tag = e.OriginalSource;
    int ind = 0;
    foreach (var _item in treeView1.Items)
    {
        if (_item == treeView1.SelectedItem)
        {
            selectedIndex = ind;
            break;
        }
        ind++;
    }
}

In the else part, The child.Parentalways returns null. I tried other methods but none of them return a TreeViewIteminstead they return DependencyObjector ItemsControl.

在 else 部分, Thechild.Parent始终返回 null。我尝试了其他方法,但没有一个返回 aTreeViewItem而是返回DependencyObjector ItemsControl

I also tried ContainerFromItemmethod but it only works for direct children(parent) and not the children of the parent.

我也尝试过ContainerFromItem方法,但它只适用于直接的孩子(父母)而不是父母的孩子。

Please help

请帮忙

回答by Metlam

You could use the VisualTreeHelper.GetParent()method: https://msdn.microsoft.com/de-de/library/system.windows.media.visualtreehelper.getparent(v=vs.110).aspx

您可以使用该VisualTreeHelper.GetParent()方法:https: //msdn.microsoft.com/de-de/library/system.windows.media.visualtreehelper.getparent(v=vs.110).aspx

Example Code:

示例代码:

private TreeViewItem FindParentTreeViewItem(object child)
{
    try
    {
        var parent = VisualTreeHelper.GetParent(child as DependencyObject);
        while ((parent as TreeViewItem) == null)
        {
            parent = VisualTreeHelper.GetParent(parent);
        }
        return parent as TreeViewItem;
    }
    catch (Exception e)
    {
        //could not find a parent of type TreeViewItem
        return null;
    }
}

The while loop is needed, as the visual parent of a tree view item isn't its parent tree view item as can be seen in this WPF Tree Visualizer:

需要 while 循环,因为树视图项的可视父项不是其父树视图项,如在此 WPF Tree Visualizer 中所示:

WPF Tree Visualizer showing tree view

WPF Tree Visualizer 显示树视图

回答by Bizhan

ItemsSourceis typically a collection of DependencyObjects which you can bind to. It doesn't reflect any information about UI. What you are looking for is actually the ItemContainer of each Item which is a part of WPF UI.

ItemsSource通常是DependencyObject您可以绑定到的s的集合。它不反映有关 UI 的任何信息。您要查找的实际上是每个 Item 的 ItemContainer,它是 WPF UI 的一部分。

In most cases you can access a UIElement from another without any problem. But in my experience as the UI gets complicated by Styles, Templates and hierarchical items, some UIElements will be hard to find.

在大多数情况下,您可以毫无问题地从另一个 UIElement 访问。但是根据我的经验,随着 UI 被样式、模板和分层项变得复杂,一些 UIElements 将很难找到。

I suggest the following way:

我建议采用以下方式:

Implement a Parent property in your ViewModel (Person Class) with type of Person and initialize it in the constructor of Person, Then you can get both the parent Person and the parent TreeViewItem like this:

在您的 ViewModel(Person 类)中实现一个 Person 类型的 Parent 属性,并在 Person 的构造函数中对其进行初始化,然后您可以像这样获得父 Person 和父 TreeViewItem:

var parentPerson = (treeView1.SelectedItem as Person).Parent;
var parentNode = treeView1.ItemContainerGenerator.ContainerFromItem(parentPerson);