如何在树视图中获取所有扩展节点?

我有一个包含TreeView的程序。 除根之外的所有节点和根目录下的两个节点都是从数据库加载的。

当用户将数据添加到数据库时,它必须自动添加到TreeView中。 我可以通过清除所有节点,添加默认节点并将包括新数据在内的所有数据添加到我的TreeView中来成功完成此操作,但新TreeView的所有节点都将折叠。

我们的客户希望保留所有扩展节点,但仍然添加他刚刚添加的新数据。 有没有办法知道所有扩展节点并在折叠或刷新后再次展开? 谢谢你的回复。

嗨据我了解,您想要在刷新树视图后保存树视图(通过添加新数据甚至删除一些),您希望展开所有展开的节点,另一个是默认折叠的。 解决方案是:

1)在刷新之前保存扩展的树视图节点

2)刷新树视图数据(注意,如果要删除节点,也要从保存的列表中删除它)

3)设置之前保存的树视图

保存树视图(仅扩展节点) – >此代码查看树视图节点集并保存扩展节点字符串列表中的名称

List collectExpandedNodes(TreeNodeCollection Nodes) { List _lst = new List(); foreach (TreeNode checknode in Nodes) { if (checknode.IsExpanded) _lst.Add(checknode.Name); if (checknode.Nodes.Count > 0) _lst.AddRange(collectExpandedNodes(checknode.Nodes)); } return _lst; } 

现在您已经在列表中收集了扩展节点名称,并且您希望获得树视图外观,您需要2个函数,一个函数通过名称和扩展所选节点的函数检索节点,它的父节点如下所示:

如果树节点集合中存在节点,则此函数将检索指向所选节点名称的指针

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

和此函数展开节点及其父节点

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

以下显示了这些function的用法

 private void button4_Click(object sender, EventArgs e) { //saving expanded nodes List ExpandedNodes = new List(); 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); } } } 

对于扩展所有节点使用下面的代码

 treeView1.ExpandAll(); 

用于扩展所选节点使用下面的代码

 treeView1.SelectedNode.ExpandAll(); 

用于扩展代码下方的特定节点使用

 treeView1.Nodes[Index].Expand(); 

要简单地展开节点,您可以尝试以下代码

  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(); } 

希望有所帮助

这很简单。 下面,您可以看到我的递归版本:

 //List of storage ids of expanded nodes List expandedNodeIds = new List(); //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); } } 

假设Nodename是独一无二的。

  • 使用数据库,节点名可以是表的唯一rowid
  • 树的状态(List)可以使用Formatter(例如BinaryFormatter )保存
    • 如果用户想要保存状态

仅保存extendedstate

 private List SaveTreeState(TreeNodeCollection nodes) { List nodeStates = new List(); foreach (TreeNode node in nodes) { if (node.IsExpanded) nodeStates.Add(node.Name); nodeStates.AddRange(SaveTreeState(node.Nodes)); } return (nodeStates); } 

让treeview完成查找恢复节点的工作

 private void RestoreTreeState(TreeView tree, List 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(); } } 

使用:

 List StateList = SaveTreeState(treeView1.Nodes); ... // reload RestoreTreeState(treeView1, StateList); 

我知道这篇文章很老但是如果树很深,那么使用树的递归遍历可能不是一个好主意。 由于我没有看到任何使用非递归方式的anwser,因此这是一种在不影响性能的情况下获取扩展节点的解决方案。

 public static IEnumerable CollectExpandedNodes(this TreeNodeAdv root) { Stack s = new Stack(); 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); } } } 

要使用此方法,您可以执行以下操作:

 foreach (TreeNodeAdv expandedNode in yourTreeView.Root.CollectExpandedNodes()) { //Do processing on the expanded node or add in list. } 

此扩展方法在后序中使用Deep-First遍历以及yield关键字来生成IEnumerable集合 。