如何轻松地遍历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);
}
}
}
(是的,目的只是修剪两层深度树的节点。)
答案 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)
虽然迭代,您可以构建一个未经检查的项目的新列表,然后将您的树视图重新绑定到该新列表(丢弃旧的列表)。