过滤包含所有节点和子节点的 TreeView
Posted
技术标签:
【中文标题】过滤包含所有节点和子节点的 TreeView【英文标题】:Filter TreeView with all nodes and childs 【发布时间】:2020-08-28 23:41:14 【问题描述】:我有一个父节点有一个孩子,这个孩子有另一个孩子等等。他们都在TreeView
所以我创建了一个全局变量来将我的所有节点保存为:
private TreeNodeCollection ProjectTreeView get; set;
然后我将树节点的数据设置到我的全局变量中:
ProjectTreeView = this.tvProjectList.Nodes[0].Nodes;
当我单击一个按钮时,我想过滤我的 TreeView,所以首先我清除 TreeView,然后我遍历集合并只显示满足我的条件的节点:
private void rdoIssued_Click(object sender, EventArgs e)
//blocks repainting tree till all objects loaded
this.tvProjectList.BeginUpdate();
this.tvProjectList.Nodes.Clear();
foreach (TreeNode projectNode in ProjectTreeView)
if (bool.Parse(projectNode.Tag.ToString().Split('|')[8]) == true)
this.tvProjectList.Nodes.Add((TreeNode)projectNode.Clone());
//enables redrawing tree after all objects have been added
this.tvProjectList.EndUpdate();
问题是它只克隆第一个节点而不是子节点。如何克隆一个包含所有子节点的节点?
【问题讨论】:
您需要递归地克隆每个节点。Clone
方法只创建一个浅拷贝。您是否尝试过不创建克隆?所有孩子都已附加到projectNode
,如果您将其添加到树中,则应该跟随他们的父母。
【参考方案1】:
做相反的事情要容易得多。您可以遍历所有节点以保留过滤的节点并删除其余节点。首先,为 0 级节点创建备份。
public partial class YourForm : Form
public YourForm()
InitializeComponent();
//...
BackUpTree();
private List<TreeNode> ProjectTreeView = new List<TreeNode>();
private void BackUpTree()
if (ProjectTreeView.Count == 0)
foreach (TreeNode tn in tvProjectList.Nodes)
ProjectTreeView.Add(tn.Clone() as TreeNode);
创建一个方法来重置原始树:
private void ResetTree(bool expandAll = false)
tvProjectList.BeginUpdate();
tvProjectList.Nodes.Clear();
foreach (var tn in ProjectTreeView)
tvProjectList.Nodes.Add(tn.Clone() as TreeNode);
if (expandAll) tvProjectList.ExpandAll();
tvProjectList.EndUpdate();
获取所有节点的迭代器函数:
private IEnumerable<TreeNode> GetAllNodes(TreeNodeCollection Nodes)
foreach (TreeNode tn in Nodes)
yield return tn;
foreach (TreeNode child in GetAllNodes(tn.Nodes))
yield return child;
...以及过滤部分的方法:
private void FilterTree(bool expandAll = false)
ResetTree(); // <- comment if you are doing multiple filters...
tvProjectList.BeginUpdate();
//.Reverse() is required here to iterate backward because the collections
//are modified when removing nodes. You can call .ToList() instead to
//iterate forward.
foreach (var node in GetAllNodes(tvProjectList.Nodes).Reverse())
if (bool.Parse(projectNode.Tag.ToString().Split('|')[8]) == false)
if (node.Parent is null)
tvProjectList.Nodes.Remove(node);
else
node.Parent.Nodes.Remove(node);
if (expandAll) tvProjectList.ExpandAll();
tvProjectList.EndUpdate();
【讨论】:
以上是关于过滤包含所有节点和子节点的 TreeView的主要内容,如果未能解决你的问题,请参考以下文章