C# 如何在树视图中获取所有展开的节点?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14596723/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I get all expanded nodes in treeview?
提问by Brenelyn
I have a program that contains a TreeView. All of my nodes except for the root and two nodes under the root are loaded from a database.
我有一个包含 TreeView 的程序。除了根和根下的两个节点之外,我的所有节点都是从数据库加载的。
When the user adds data to the database it must be automatically added to the TreeView. I can successfully do this by clearing all the nodes, add the default nodes and add all the data including the new one to my TreeView, but all nodes of the new TreeView are collapsed.
当用户将数据添加到数据库时,它必须自动添加到 TreeView。我可以通过清除所有节点、添加默认节点并将包括新节点在内的所有数据添加到我的 TreeView 来成功执行此操作,但新 TreeView 的所有节点都已折叠。
Our client wants to retain all expanded nodes but still add the new data he just added. Is there any way to know all expanded nodes and expand it again once collapsed or refreshed? Thank you for any response.
我们的客户希望保留所有扩展的节点,但仍要添加他刚刚添加的新数据。有没有办法知道所有展开的节点并在折叠或刷新后再次展开它?感谢您的任何回应。
回答by Rohit
To simply expand nodes you can try this following code
要简单地扩展节点,您可以尝试以下代码
private void button1_Click(object sender, EventArgs e)
{
treeView1.Nodes.Add(new TreeNode("New Node",
new TreeNode[2] { new TreeNode("Node1"), new TreeNode("Node2") }));
treeView1.Nodes[1].Expand();
}
Hope that helps
希望有帮助
回答by andy
For expanding all the nodes use below code
要扩展所有节点,请使用以下代码
treeView1.ExpandAll();
For expanding selected node use below code
要扩展所选节点,请使用以下代码
treeView1.SelectedNode.ExpandAll();
For expanding particular node use below code
为了扩展特定节点使用下面的代码
treeView1.Nodes[Index].Expand();
回答by saeed
Hi As i understand you want to save you tree view map after you refresh tree view (by adding new data or even remove some) you want to expand all expanded nodes the other are collapsed by default. Solution is:
嗨,据我所知,您想在刷新树视图(通过添加新数据甚至删除一些数据)后保存树视图地图,您想展开所有展开的节点,其他节点默认折叠。解决办法是:
1) save expanded tree view nodes before refresh
1) 在刷新前保存展开的树视图节点
2) refresh tree view data (notice that if you are removing a node , remove it from saved list as well)
2)刷新树视图数据(请注意,如果您要删除节点,请将其从保存的列表中删除)
3) set tree view map which saved before
3) 设置之前保存的树状图
saving tree view map (only expanded nodes)-> This Code Look through a tree view node collection and saves expanded nodes Names in a string list
保存树视图地图(仅扩展节点)-> 此代码查看树视图节点集合并将扩展节点名称保存在字符串列表中
List<string> collectExpandedNodes(TreeNodeCollection Nodes)
{
List<string> _lst = new List<string>();
foreach (TreeNode checknode in Nodes)
{
if (checknode.IsExpanded)
_lst.Add(checknode.Name);
if (checknode.Nodes.Count > 0)
_lst.AddRange(collectExpandedNodes(checknode.Nodes));
}
return _lst;
}
Now you have collected expanded nodes name in a list and you want to gain back your tree view appearance you need 2 functions a function which retrieves node by a name and a function which expand selected node and it's parents the following codes does :
现在您已经在列表中收集了扩展节点名称,并且想要恢复树视图外观,您需要 2 个函数,一个是按名称检索节点的函数,另一个是扩展所选节点及其父节点的函数,以下代码执行:
This function retrieves a pointer to selected node Name if node is exist in Tree Node Collection
如果节点存在于树节点集合中,则此函数检索指向选定节点名称的指针
TreeNode FindNodeByName(TreeNodeCollection NodesCollection , string Name)
{
TreeNode returnNode = null; // Default value to return
foreach (TreeNode checkNode in NodesCollection)
{
if (checkNode.Name == Name) //checks if this node name is correct
returnNode = checkNode;
else if (checkNode.Nodes.Count > 0 ) //node has child
{
returnNode = FindNodeByName(checkNode.Nodes , Name);
}
if (returnNode != null) //check if founded do not continue and break
{
return returnNode;
}
}
//not found
return returnNode;
}
and This Function Expand node and it's parents
和此功能扩展节点及其父节点
void expandNodePath(TreeNode node)
{
if (node == null)
return;
if (node.Level != 0) //check if it is not root
{
node.Expand();
expandNodePath(node.Parent);
}
else
{
node.Expand(); // this is root
}
}
and the following show you the usage of the functions
下面向您展示了这些功能的用法
private void button4_Click(object sender, EventArgs e)
{
//saving expanded nodes
List<string> ExpandedNodes = new List<string>();
ExpandedNodes = collectExpandedNodes(treeView1.Nodes);
//resetting tree view nodes status to colapsed
treeView1.CollapseAll();
//Restore it back
if (ExpandedNodes.Count > 0)
{
TreeNode IamExpandedNode;
for (int i = 0; i < ExpandedNodes.Count;i++ )
{
IamExpandedNode = FindNodeByName(treeView1.Nodes, ExpandedNodes[i]);
expandNodePath(IamExpandedNode);
}
}
}
回答by isxaker
It's very simple. Below, you can see my recursive version:
这很简单。在下面,您可以看到我的递归版本:
//List of storage ids of expanded nodes
List<int> expandedNodeIds = new List<int>();
//call recursive fun for our tree
CollectExpandedNodes(tree.Nodes);
//recursive fun for collect expanded node ids
private void CollectExpandedNodes(TreeListNodes nodes)
{
foreach (TreeListNode node in nodes)
{
if (node.Expanded) expandedNodeIds.Add(node.Id);
if (node.HasChildren) CollectExpandedNodes(node.Nodes);
}
}
回答by D. Herzog
Assume the Nodename is unique.
假设 Nodename 是唯一的。
- Using an Database the nodename can be the unique rowid of an table
- The state of the tree (List) can simply saved with an Formatter (e.g. BinaryFormatter)
- if User want to save status
- 使用数据库,节点名可以是表的唯一 rowid
- 树(列表)的状态可以简单地用格式化程序(例如BinaryFormatter)
保存
- 如果用户想要保存状态
Only save the expandedstate
只保存扩展状态
private List<string> SaveTreeState(TreeNodeCollection nodes)
{
List<string> nodeStates = new List<string>();
foreach (TreeNode node in nodes)
{
if (node.IsExpanded) nodeStates.Add(node.Name);
nodeStates.AddRange(SaveTreeState(node.Nodes));
}
return (nodeStates);
}
Let the treeview do the work finding the nodes for restore
让树视图完成查找要还原的节点的工作
private void RestoreTreeState(TreeView tree, List<string> treeState)
{
foreach (string NodeName in treeState)
{
TreeNode[] NodeList = treeView1.Nodes.Find(NodeName, true);
if (NodeList.Length > 0) // only if node after reload is avail
NodeList[0].Expand();
}
}
Using:
使用:
List<string> StateList = SaveTreeState(treeView1.Nodes);
... // reload
RestoreTreeState(treeView1, StateList);
回答by SniperLegacy
I know this post is old but if the tree is deep it might not be a good idea to use a recursive traversal of the tree. Since I have not seen any anwser using a non-recursive way here is a solution for doing getting expanded nodes without impacting performance.
我知道这篇文章很旧,但如果树很深,使用树的递归遍历可能不是一个好主意。由于我还没有看到任何使用非递归方式的 anwser,这里是一种在不影响性能的情况下获取扩展节点的解决方案。
public static IEnumerable<TreeNodeAdv> CollectExpandedNodes(this TreeNodeAdv root)
{
Stack<TreeNodeAdv> s = new Stack<TreeNodeAdv>();
s.Push(root);
while (s.Count > 0)
{
TreeNodeAdv n = s.Pop();
if (n.IsExpanded)
yield return n;
foreach (var child in n.Children.ToArray().Reverse())
{
s.Push(child);
}
}
}
To use this method, you can do the following:
要使用此方法,您可以执行以下操作:
foreach (TreeNodeAdv expandedNode in yourTreeView.Root.CollectExpandedNodes())
{
//Do processing on the expanded node or add in list.
}
This extension methoduses Deep-First traversalin post-orderalong with the yield keywordto generate an IEnumerable collection.
该扩展方法使用深度优先遍历在后序与一起产量关键字生成IEnumerable集合。