WPF:TreeView获取父节点

时间:2016-04-23 03:19:02

标签: c# wpf treeview

问题解释简短:

 Node 1
     Child x
     Child Y
 Node 2
     Child z

在处理TreeView类型时,在选择父节点时,SelectedItem属性返回类型为TreeViewItem的对象,以下内容正常工作

 TreeViewItem parentNode = (TreeViewItem) treeView.SelectedItem;

这时,当选择一个节点的值时,此属性返回String,这意味着在这种情况下将满足以下条件:

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

因此,我们不能再将对象强制转换为TreeViewItem

假设你有以下

IEnumerable<IGrouping<String, Childs>> treeModel;

并且您想知道子项属于哪个节点,您将如何从TreeView获取父节点元素。

3 个答案:

答案 0 :(得分:0)

原始答案

  

TreeView.ItemContainerGenerator.ContainerFromItem可以做到这一点:https://msdn.microsoft.com/en-us/library/system.windows.controls.itemcontainergenerator.containerfromitem(v=vs.110).aspx

新答案

首先,你有一个IEnumerable<IGrouping<String, Childs[]>>类型的树模型很奇怪:

  • 不应该是IEnumerable<IGrouping<String, Childs>>吗?否则,您将使用Childs数组作为节点的模型,而不是单个Childs
  • 如何使用树分配模型?如果您绑定它们,则永远不会获得具有String模型的父节点,因为它应该是IGrouping<String, Childs[]>类型(如果接受最后一个点,则为IGrouping<String, Childs>)。然后,您的问题就找到了TreeViewItem IGrouping的相应内容,可以使用ItemContainerGenerator.ContainerFromItem来完成。您也不能手动创建这样的层次结构,因为如果您将String项添加到TreeView中,您怎么能为它添加子项?

如果我们忽略这些怪癖,只要假设你的TreeView中有这样的模型层次结构:

 string Node1
     Childs ChildX
     Childs ChildY
 string Node2
     Childs ChildZ

现在你想得到一个孩子的相应TreeViewItem,说ChildY。你的问题在于,你无法从TreeView.ItemContainerGenerator获得它,因为它不存在,不像你想象的那样,如果它的模型是一个字符串,你就无法得到它。您只能在其父TreeViewItem TreeViewItem中找到ItemContainerGenerator

在这种情况下,您必须递归遍历树,在每个TreeViewItem的{​​{1}}中找到子容器。

答案 1 :(得分:0)

不幸的是,SO中的所有帖子都指出错误的解决方案,或者由于我解释的原因而导致解决方案可能不再有效。 (这同样适用于所有Microsoft文档,可能已过时)

似乎没有**Built-In**功能,所以决定设计我自己的解决方案。通过创建自定义的TreeViewItem类并添加ParentNodeValue属性,可以解决此问题。

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

我们可以执行以下操作来获取节点值:

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

在这种方法中,SelectedItem属性无法返回String

答案 2 :(得分:0)

将对象强制转换为TreeViewItem是正确的。它每次都返回null。我遇到了一个非常类似的问题,这是我找到的解决方案。

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

这是搜索子节点父节点的主要功能。

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

现在您可以将此代码用作

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

我希望它会帮助很多人患上同样的问题。虽然解决方案很简单,但我发布了这个,因为我也浪费了太多时间寻找解决方案。