2
votes

Problem explained short:

 Node 1
     Child x
     Child Y
 Node 2
     Child z

When dealing with TreeView type, when selecting a parent node, the SelectedItem property returns an object of type TreeViewItem and the following works properly

 TreeViewItem parentNode = (TreeViewItem) treeView.SelectedItem;

This while, this property return a String when a value of a node is selected which means in that case the following will be true:

 Boolean valueType = treeView.SelectedItem is String; --> True 

Accordingly, we cannot cast the object to the TreeViewItem anymore.

Assuming you got the following

IEnumerable<IGrouping<String, Childs>> treeModel;

And you want to know to which node the child belongs, how would you obtain the parent node element from the TreeView.

3

3 Answers

0
votes

Unfortunately all post in SO point out to the wrong solution, or a solution which may no longer work due to the reason I explained. (The same applies to all Microsoft documentation, maybe outdated)

There seems to be no **Built-In** feature to this, so decided to design my own solution. This problem can be solved, by creating a customized TreeViewItem class and adding a ParentNodeValue property.

public class AdvancedTreeViewItem<T>: TreeViewItem{
    public T ParentNodeValue {get; set;}
    public T RootParentNodeValue {get; set;}
}

And we can do the following to get the node value:

var selectedValue = (AdvancedTreeViewItem<String>)treeView.SelectedItem;
MessageBox.Show(selectedValue.RootParentNodeValue);

In this approach, there is no way the SelectedItem property would return a String

0
votes

Original Answer

TreeView.ItemContainerGenerator.ContainerFromItem should do the trick: https://msdn.microsoft.com/en-us/library/system.windows.controls.itemcontainergenerator.containerfromitem(v=vs.110).aspx

New Answer

First of all, it's weird you have a tree model of type IEnumerable<IGrouping<String, Childs[]>>:

  • Shouldn't it be IEnumerable<IGrouping<String, Childs>>? Otherwise you will have a Childs array as the model of a node, rather than a single Childs.
  • How do you assign the model with the tree? If you are binding them, you will never get a parent node with a String model, because it should be of type IGrouping<String, Childs[]> (or IGrouping<String, Childs> if the last point is accepted). Then your problem became finding the corresponding TreeViewItem of that IGrouping thing, which could be done with ItemContainerGenerator.ContainerFromItem. You can't make such a hierarchy manually, neither, because if you add a String item into a TreeView, how could you add Children for it?

And if we ignore these quirks, just assume you have such a model hierarchy in your TreeView:

 string Node1
     Childs ChildX
     Childs ChildY
 string Node2
     Childs ChildZ

Now you want to get the corresponded TreeViewItem of a child, say ChildY. Your problem here is, you cannot get it from TreeView.ItemContainerGenerator, because it is not there, not as you assumed, you can't get it if its model is a string. You can only find that TreeViewItem in its parent TreeViewItem's ItemContainerGenerator.

In this case, you have to traverse down the tree recursively, find the container of the child in every TreeViewItem's ItemContainerGenerator.

0
votes

You are right about casting the object to the TreeViewItem. It returns null every-time. I had a very similar problem to you and here is the solution that I found.

Node GetSelectedParentNode(){
object selectedItem = treeView.SelectedItem;
if(selectedItem == null)
    return null;   // No item is selected in treeview
else if(selectedItem is Node)
    return selectedItem;      // You already have a parent node selected
else if(selectedItem is Child)
    return FindParentNode(selectedItem as Child);   // Your main task
else
    return null;  // Exception case...
}

here is main function to search parent of a child node.

Node FindParentNode(Child child){
    // assume you have some list of Node binding to treeview
    foreach(Node node in NodesList)
         if(node.childs.Contains(child)
             return node;      // here is your target parent node
    return null;   // Exception case..
}

Now you can use this code as

Node parentNode = GetSelectedParentNode();
// Do your stuff here..

I hope it will help a lot of people suffering from same problem. Although solution is very simple but I posted this because I also have wasted my too much time searching for solution.