C# 如何有效地从树视图中删除选中的项目?

C# 如何有效地从树视图中删除选中的项目?,c#,.net,winforms,treeview,iteration,C#,.net,Winforms,Treeview,Iteration,如何轻松地遍历树视图中的所有节点,检查它们的.Checked属性,然后删除所有选中的节点 这看起来很简单,但您不应该修改要迭代的集合,从而消除了“foreach”循环的可能性。(.Nodes.Remove调用正在修改集合。)如果尝试此操作,其效果是仅删除约一半的.Checked节点 即使要使用两个过程:首先创建临时索引列表,然后在第二个过程中按索引删除——每次删除时索引都会更改,从而使索引列表的完整性无效 那么,最有效的方法是什么呢 下面是一个代码示例,看起来不错,但实际上只删除了大约一半的.C

如何轻松地遍历树视图中的所有节点,检查它们的.Checked属性,然后删除所有选中的节点

这看起来很简单,但您不应该修改要迭代的集合,从而消除了“foreach”循环的可能性。(.Nodes.Remove调用正在修改集合。)如果尝试此操作,其效果是仅删除约一半的.Checked节点

即使要使用两个过程:首先创建临时索引列表,然后在第二个过程中按索引删除——每次删除时索引都会更改,从而使索引列表的完整性无效

那么,最有效的方法是什么呢

下面是一个代码示例,看起来不错,但实际上只删除了大约一半的.Checked节点:

            foreach (TreeNode parent in treeView.Nodes)
            {
                if (parent.Checked)
                {
                    treeView.Nodes.Remove(parent);
                }
                else
                {
                    foreach (TreeNode child in parent.Nodes)
                    {
                        if (child.Checked) parent.Nodes.Remove(child);
                    }
                }
            }

(是的,目的只是从两层深的树中删除节点。)

迭代时,您可以构建一个未检查项的新列表,然后将树视图重新绑定到该新列表(丢弃旧列表)。

尝试向后遍历节点。这样,索引的增加不会超过节点大小:

for( int ndx = nodes.Count; ndx > 0; ndx--) { TreeNode node = nodes[ndx-1]; if (node.Checked) { nodes.Remove(node); } // Recurse through the child nodes... } 对于(int ndx=nodes.Count;ndx>0;ndx--) { 树节点=节点[ndx-1]; 如果(节点已选中) { 节点。移除(节点); } //通过子节点递归。。。 }
这将在枚举节点后删除它们,并且可以递归地用于n层节点

void RemoveCheckedNodes(TreeNodeCollection nodes)
{
    List<TreeNode> checkedNodes = new List<TreeNode>();

    foreach (TreeNode node in nodes)
    {
        if (node.Checked)
        {
            checkedNodes.Add(node);
        }
        else
        {
            RemoveCheckedNodes(nodes.ChildNodes);
        }
    }

    foreach (TreeNode checkedNode in checkedNodes)
    {
        nodes.Remove(checkedNode);
    }
}
void RemoveCheckedNodes(TreeNodeCollection节点)
{
List checkedNodes=新列表();
foreach(节点中的树节点)
{
如果(节点已选中)
{
checkedNodes.Add(节点);
}
其他的
{
移除checkednodes(nodes.ChildNodes);
}
}
foreach(checkedNodes中的TreeNode checkedNode)
{
节点。删除(选中节点);
}
}

如果要高效地执行此操作,需要在检查节点时跟踪它们。将选中的树节点存储在列表中(并在未选中时将其删除)

如果你有一个唯一的键和很多节点来跟踪,你也可以考虑一个字典。但是,如果你只处理10-50,可能不会有很大的区别


然后,不要在整个树中循环,只需在(较小的)节点列表中循环。

这是最有效的方法。老问题,但+1是最有效的方法。再次访问此。。。几次修改会使它稍微快一点。。。在for循环标题中进行以下更改:
int ndx=nodes.Count-1
ndx>=0
将允许您避免每次通过循环时出现-1。在大计划的事情,一些额外的减法将不会有多大的意义,但嘿。。。为什么不呢?