C# 如何有效地从树视图中删除选中的项目?
如何轻松地遍历树视图中的所有节点,检查它们的.Checked属性,然后删除所有选中的节点 这看起来很简单,但您不应该修改要迭代的集合,从而消除了“foreach”循环的可能性。(.Nodes.Remove调用正在修改集合。)如果尝试此操作,其效果是仅删除约一半的.Checked节点 即使要使用两个过程:首先创建临时索引列表,然后在第二个过程中按索引删除——每次删除时索引都会更改,从而使索引列表的完整性无效 那么,最有效的方法是什么呢 下面是一个代码示例,看起来不错,但实际上只删除了大约一半的.Checked节点:C# 如何有效地从树视图中删除选中的项目?,c#,.net,winforms,treeview,iteration,C#,.net,Winforms,Treeview,Iteration,如何轻松地遍历树视图中的所有节点,检查它们的.Checked属性,然后删除所有选中的节点 这看起来很简单,但您不应该修改要迭代的集合,从而消除了“foreach”循环的可能性。(.Nodes.Remove调用正在修改集合。)如果尝试此操作,其效果是仅删除约一半的.Checked节点 即使要使用两个过程:首先创建临时索引列表,然后在第二个过程中按索引删除——每次删除时索引都会更改,从而使索引列表的完整性无效 那么,最有效的方法是什么呢 下面是一个代码示例,看起来不错,但实际上只删除了大约一半的.C
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);
}
}
}
(是的,目的只是从两层深的树中删除节点。)迭代时,您可以构建一个未检查项的新列表,然后将树视图重新绑定到该新列表(丢弃旧列表)。尝试向后遍历节点。这样,索引的增加不会超过节点大小: for( int ndx = nodes.Count; ndx > 0; ndx--) { TreeNode node = nodes[ndx-1]; if (node.Checked) { nodes.Remove(node); } // Recurse through the child nodes... } 对于(int ndx=nodes.Count;ndx>0;ndx--) { 树节点=节点[ndx-1]; 如果(节点已选中) { 节点。移除(节点); } //通过子节点递归。。。 }
这将在枚举节点后删除它们,并且可以递归地用于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);
}
}
void RemoveCheckedNodes(TreeNodeCollection节点)
{
List checkedNodes=新列表();
foreach(节点中的树节点)
{
如果(节点已选中)
{
checkedNodes.Add(节点);
}
其他的
{
移除checkednodes(nodes.ChildNodes);
}
}
foreach(checkedNodes中的TreeNode checkedNode)
{
节点。删除(选中节点);
}
}
如果要高效地执行此操作,需要在检查节点时跟踪它们。将选中的树节点存储在列表中(并在未选中时将其删除)
如果你有一个唯一的键和很多节点来跟踪,你也可以考虑一个字典。但是,如果你只处理10-50,可能不会有很大的区别
然后,不要在整个树中循环,只需在(较小的)节点列表中循环。这是最有效的方法。老问题,但+1是最有效的方法。再次访问此。。。几次修改会使它稍微快一点。。。在for循环标题中进行以下更改:
int ndx=nodes.Count-1
和ndx>=0
将允许您避免每次通过循环时出现-1。在大计划的事情,一些额外的减法将不会有多大的意义,但嘿。。。为什么不呢?