【问题标题】:Filter TreeView with all nodes and childs过滤包含所有节点和子节点的 TreeView
【发布时间】: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,如果您将其添加到树中,则应该跟随他们的父母。

标签: c# winforms treeview


【解决方案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();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-17
    • 1970-01-01
    • 1970-01-01
    • 2020-05-15
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    • 2014-01-02
    相关资源
    最近更新 更多