7

如何轻松遍历 TreeView 中的所有节点,检查它们的 .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);
                    }
                }
            }

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

4

4 回答 4

8

Try walking through the nodes backwards. That way your index doesn't increase past your node size:

for( int ndx = nodes.Count; ndx > 0; ndx--)
{
  TreeNode node = nodes[ndx-1];
  if (node.Checked)
  {
     nodes.Remove(node);
  }
   // Recurse through the child nodes...
}
于 2009-05-05T15:17:43.850 回答
7

This will remove the nodes after enumerating them, and can be used recursively for n-tiers of nodes.

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);
    }
}
于 2009-05-05T15:22:10.847 回答
3

如果你想有效地做到这一点,你需要在检查节点时跟踪它们。将选中的树节点存储在列表中(并在它们未选中时将其删除)。

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

然后,不是循环遍历整个树,而是循环遍历(较小的)节点列表。

于 2009-05-05T15:35:17.240 回答
1

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

于 2009-05-05T15:17:24.243 回答