Como excluir eficiente Itens verificado a partir de um TreeView?
Pergunta
Como se pode facilmente percorrer todos os nós em um TreeView, examinar sua propriedade .checked e exclua todos nós verificado?
Parece simples, mas você não deve modificar uma coleção através do qual você é a iteração, eliminando a possibilidade de um loop "foreach". (A chamada .Nodes.Remove é modificar a recolha.) Se este for tentada, o efeito é que apenas cerca de metade dos nós .checked são removidos.
Mesmo que se utilizar duas passagens: em primeiro lugar a criação de uma lista de índices temporários, e removendo depois por índice na segunda passagem - os índices se alteraria com cada remoção, invaliding a integridade da lista de dice.
Então, o que é a maneira mais eficiente de fazer isso?
Aqui está um exemplo de código que parece ser bom, mas na verdade só remove cerca de metade dos nós .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);
}
}
}
(Sim, a intenção é apenas para nós poda de uma árvore que é de dois níveis de profundidade.)
Solução
Isto irá remover os nós depois de enumerar-los, e pode ser usado de forma recursiva para n-tiers de nós.
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);
}
}
Outras dicas
Tente andar através dos gânglios para trás. Dessa forma, o índice de não aumentar passado o seu tamanho nó:
for( int ndx = nodes.Count; ndx > 0; ndx--) { TreeNode node = nodes[ndx-1]; if (node.Checked) { nodes.Remove(node); } // Recurse through the child nodes... }
Se você quiser fazê-lo de forma eficiente você precisa manter o controle dos nós verificados como eles são verificados. Armazenar os nós da árvore verificados em uma lista (e removê-los como eles são desmarcada).
Se você tem uma chave única e um monte de nós para manter o controle de que você pode considerar um dicionário também. Mas se você está lidando apenas com 10-50 provavelmente não vai fazer uma grande diferença.
Então, em vez de loop através de toda a árvore que você acabou de loop thru sua lista (menor) de nós.
Enquanto a iteração você poderia construir uma nova lista de itens sem controle e, em seguida, re-bind sua árvore para que a nova lista (descartando o antigo).