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
得到它,因为它不存在,不像你假设的那样,如果它的模型是一个字符串,你就不能得到它。你只能在它的parentTreeViewItem
的ItemContainerGenerator
.
中找到那个TreeViewItem
这样的话,就得递归向下遍历树,在每个TreeViewItem
的ItemContainerGenerator
.
中找到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..
我希望它能帮助很多遇到同样问题的人。虽然解决方案很简单,但我发布了这个,因为我也浪费了太多时间寻找解决方案。
问题简述:
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
得到它,因为它不存在,不像你假设的那样,如果它的模型是一个字符串,你就不能得到它。你只能在它的parentTreeViewItem
的ItemContainerGenerator
.
TreeViewItem
这样的话,就得递归向下遍历树,在每个TreeViewItem
的ItemContainerGenerator
.
不幸的是,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..
我希望它能帮助很多遇到同样问题的人。虽然解决方案很简单,但我发布了这个,因为我也浪费了太多时间寻找解决方案。