Get parent TreeViewItem of a selected node in WPF

别说谁变了你拦得住时间么 提交于 2021-01-28 05:28:59

问题


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

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

This is my xaml code

<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.

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.Parent always returns null. I tried other methods but none of them return a TreeViewItem instead they return DependencyObject or ItemsControl.

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

Please help


回答1:


You could use the VisualTreeHelper.GetParent() method: 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:

WPF Tree Visualizer showing tree view




回答2:


ItemsSource is 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.

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.

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:

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


来源:https://stackoverflow.com/questions/26624982/get-parent-treeviewitem-of-a-selected-node-in-wpf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!