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

如何轻松遍历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); } } } 

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

这将在枚举后删除节点,并且可以递归地用于n层节点。

 void RemoveCheckedNodes(TreeNodeCollection nodes) { List checkedNodes = new List(); foreach (TreeNode node in nodes) { if (node.Checked) { checkedNodes.Add(node); } else { RemoveCheckedNodes(nodes.ChildNodes); } } foreach (TreeNode checkedNode in checkedNodes) { nodes.Remove(checkedNode); } } 

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

 for(int ndx = nodes.Count; ndx> 0; ndx--)
 {
   TreeNode节点=节点[ndx-1];
   if(node.Checked)
   {
      nodes.Remove(节点);
   }
    //通过子节点递归...
 }

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

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

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

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