Get parent TreeViewItem of a selected node in WPF
Asked Answered
U

2

1

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

Uncoil answered 29/10, 2014 at 7:39 Comment(1)
Navigating through WPF UI is sometimes very tricky. If you couldn't find a way to achieve this, simply try adding a Parent in your Person class which makes the navigation so much easier.Ruggiero
B
2

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

Balliett answered 10/8, 2017 at 15:15 Comment(0)
R
0

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);
Ruggiero answered 29/10, 2014 at 8:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.