1
votes

I have a treeview with the following structure:

Attribute1
  --Value11
  --Value12
Attribute2
  --Value21
  --...
...

The treeview is populated with an HierarchicalDataTemplate of custom classes Attribute and Value.

Now I need to get the parent (attribute) of the currently selected item (value).

What I tried:

DependencyObject obj = treeViewAttributes.ItemContainerGenerator.ContainerFromItem(treeViewAttributes.Items.CurrentItem);
DependencyObject parentNode = ((TreeViewItem)obj).Parent;
Attribute parentAttribute = treeViewAttributes.ItemContainerGenerator.ItemFromContainer(obj) as AttributeType;

However the first line doesn't retrieve the selected object, but the root node. And ContainerFromItem(treeViewAttributes.SelectedItem) returns null.

4
Could you add a reference of the parent object (Attribute) to the child class (Value)?Andrew Mack
Unfortunately only the parent has a reference to its children and the classes shouldn't be altered unless there is any other possible solution.Matthias

4 Answers

1
votes

WPF has a reason not to easily return a parent of a tree node. It basically forces you to think of a TreeView in terms of logical vs visual representation. Every node in a tree logically contains an object which on its own level is always created prior to its child, so the best approach to take when you know that you will need access to a parent node is to have a reference to a parent within a child when the child is being created since the parent already always exists. This approach is way more efficient than walking the visual tree in search of a parent

0
votes

Try following code

private void yourTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
    if (sender is TreeView && ((TreeViewItem)((TreeView)sender).SelectedItem).Parent != null)
    {
        TreeViewItem parent = (TreeViewItem)((TreeViewItem)((TreeView)sender).SelectedItem).Parent;  // This will give you the parent             
    }
}
0
votes

I tried running through treeView and use GetHashCode for finding parent treeViewItem and it worked well for me. I don't know how the performance is, but I think that should not be a problem:

private TreeViewItem GetParent(TreeViewItem root, TreeViewItem child)
    {
        //Step 1: Search at current level
        foreach (TreeViewItem item in root.Items)
        {
            if (item.GetHashCode() == child.GetHashCode())
            {
                return root;
            }
        }

        //Step 2: Still not found, so step deeper
        TreeViewItem buffer;
        foreach (TreeViewItem item in root.Items)
        {
            buffer = GetParent(item, child);
            if (buffer != null)
            {
                return buffer;
            }
        }

        //Not found anything
        return null;
    }
0
votes

Use the helper class in this blog

https://rachel53461.wordpress.com/2011/10/09/navigating-wpfs-visual-tree/

    /// <summary>
    /// Returns the first ancester of specified type
    /// </summary>
    public static T FindAncestor<T>(DependencyObject current)
    where T : DependencyObject
    {
        current = VisualTreeHelper.GetParent(current);

        while (current != null)
        {
            if (current is T)
            {
                return (T)current;
            }
            current = VisualTreeHelper.GetParent(current);
        };
        return null;
    }

Then you can get the parent with this call

var parent = VisualTreeHelpers.FindAncestor<Attribute>(Value);