2009-05-05 75 views
7

如何轻松遍历TreeView中的所有节点,检查它们的.Checked属性,然后删除所有已检查的节点?如何有效地从TreeView中删除检查的项目?

看起来很简单,但你不应该修改你正在迭代的集合,从而消除了“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); 
        } 
       } 
      } 

(是的,目的是只从一个树是二修剪节点)

回答

6

这将列举它们后删除节点,可以为节点的正层次递归使用。

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); 
    } 
} 
1

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

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... 
} 
+0

这是最有效的方法。 – Romias 2009-12-24 07:53:48

3

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

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

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