如何从TreeView中有效删除已检查的项目?

时间:2009-05-05 15:08:07

标签: c# .net winforms treeview iteration

如何轻松地遍历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 个答案:

答案 0 :(得分:7)

尝试向后穿过节点。这样,您的索引不会超过您的节点大小:

for( int ndx = nodes.Count; ndx > 0; ndx--)
{
  TreeNode node = nodes[ndx-1];
  if (node.Checked)
  {
     nodes.Remove(node);
  }
   // Recurse through the child nodes...
}

答案 1 :(得分:6)

这将在枚举后删除节点,并且可以递归地用于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);
    }
}

答案 2 :(得分:3)

如果要有效地执行此操作,则需要在检查时检查已检查的节点。将选中的树节点存储在列表中(并在取消选中时将其删除)。

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

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

答案 3 :(得分:1)

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