WPF:TreeView 获取父节点

WPF: TreeView get parent node

问题简述:

 Node 1
     Child x
     Child Y
 Node 2
     Child z

处理TreeView类型时,选择父节点时,SelectedItem属性returns一个TreeViewItem及以下类型的对象正常工作

 TreeViewItem parentNode = (TreeViewItem) treeView.SelectedItem;

This while, this 属性 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 

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

假设你得到以下

IEnumerable<IGrouping<String, Childs>> treeModel;

而你想知道子节点属于哪个节点,你会如何从TreeView中获取父节点元素。

原答案

TreeView.ItemContainerGenerator.ContainerFromItem should do the trick: 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 模型的 parent 节点,因为它应该是 IGrouping<String, Childs[]> 类型(或者 IGrouping<String, Childs> 如果最后一点被接受).然后你的问题就变成了找到 IGrouping 对应的 TreeViewItem,这可以用 ItemContainerGenerator.ContainerFromItem 来完成。您也不能手动创建这样的层次结构,因为如果您将 String 项目添加到 TreeView 中,您如何为它添加 Children?

如果我们忽略这些怪癖,假设您在 TreeView:

中有这样一个模型层次结构
 string Node1
     Childs ChildX
     Childs ChildY
 string Node2
     Childs ChildZ

现在你想得到一个child对应的TreeViewItem,比如ChildY。你这里的问题是,你不能从TreeView.ItemContainerGenerator得到它,因为它不存在,不像你假设的那样,如果它的模型是一个字符串,你就不能得到它。你只能在它的parentTreeViewItemItemContainerGenerator.

中找到那个TreeViewItem

这样的话,就得递归向下遍历树,在每个TreeViewItemItemContainerGenerator.

中找到child的容器

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

这似乎没有 **Built-In** 功能,因此决定设计我自己的解决方案。通过创建自定义 TreeViewItem class 并添加 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 属性 不可能 return 一个 String

关于将对象投射到 TreeViewItem 的做法是正确的。它 returns 每次都是空的。我遇到了与您非常相似的问题,这是我找到的解决方案。

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

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