如何在树视图中获取所有扩展的节点
本文关键字:扩展 节点 获取 视图 | 更新日期: 2023-09-27 17:56:41
我有一个包含TreeView的程序。除了根和根下的两个节点之外,我的所有节点都是从数据库加载的。
当用户将数据添加到数据库时,必须自动将数据添加到树视图中。我可以通过清除所有节点、添加默认节点并将所有数据(包括新节点)添加到我的 TreeView 来成功做到这一点,但新 TreeView 的所有节点都折叠了。
我们的客户希望保留所有扩展的节点,但仍添加他刚刚添加的新数据。有没有办法知道所有扩展的节点并在折叠或刷新后再次展开它?感谢您的任何回复。
据我了解,您想在刷新树视图(通过添加新数据甚至删除一些数据)后保存树视图地图,您想展开所有扩展的节点,其他节点默认折叠。解决方案是:
1) 刷新前保存展开的树视图节点
2)刷新树视图数据(请注意,如果要删除节点,也会将其从保存列表中删除)
3)设置之前保存的树视图地图
保存树视图图(仅扩展节点)->此代码 浏览树视图节点集合并保存扩展的节点 字符串列表中的名称
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;
}
现在,您已经在列表中收集了扩展的节点名称,并且想要恢复树视图外观,您需要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
}
}
下面向您展示了函数的用法
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);
}
}
}
要扩展所有节点,请使用以下代码
treeView1.ExpandAll();
要扩展选定的节点,请使用以下代码
treeView1.SelectedNode.ExpandAll();
要扩展特定节点,请使用以下代码
treeView1.Nodes[Index].Expand();
假设节点名称是唯一的。
- 使用数据库,节点名可以是表的唯一 rowid
- 树的状态(列表)可以简单地用格式化程序保存(例如二进制格式化程序)
- 如果用户想要保存状态
仅保存展开状态
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);
}
让树视图完成查找要还原的节点的工作
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();
}
}
用:
List<string> StateList = SaveTreeState(treeView1.Nodes);
... // reload
RestoreTreeState(treeView1, StateList);
要简单地扩展节点,您可以尝试以下代码
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<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);
}
}
这篇文章很旧,但如果树很深,那么使用树的递归遍历可能不是一个好主意。由于我没有看到任何使用非递归方式的 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);
}
}
}
若要使用此方法,可以执行以下操作:
foreach (TreeNodeAdv expandedNode in yourTreeView.Root.CollectExpandedNodes())
{
//Do processing on the expanded node or add in list.
}
此扩展方法使用后序中的 Deep-First 遍历以及 yield 关键字来生成 IEnumerable 集合。