2009-05-05 8 views
7

Come si può facilmente iterare attraverso tutti i nodi in un TreeView, esaminare la loro proprietà .Checked e quindi eliminare tutti i nodi controllati?Come eliminare in modo efficiente gli elementi controllati da un TreeView?

Sembra semplice, ma non si dovrebbe modificare una raccolta attraverso cui si sta iterando, eliminando la possibilità di un ciclo "foreach". (La chiamata .Nodes.Remove sta modificando la collezione.) Se ciò viene tentato, l'effetto è che solo la metà dei nodi .Checked viene rimossa.

Anche se si dovessero utilizzare due passaggi: prima creando un elenco di indici temporanei e quindi rimuovendo per indice sul secondo passaggio, gli indici cambiano ad ogni rimozione, invalida l'integrità della lista di indici.

Quindi, qual è il modo più efficiente per farlo?

Ecco un esempio di codice che sembra buono, ma in realtà rimuove solo circa la metà dei nodi .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); 
        } 
       } 
      } 

(Sì, l'intenzione è solo per potare i nodi da un albero che è due livelli profondi.)

risposta

6

Questo eliminerà i nodi dopo di loro enumerazione, e può essere utilizzato in modo ricorsivo per n-livelli di nodi.

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

Durante l'iterazione è possibile creare un nuovo elenco di elementi non selezionati e quindi associare nuovamente la vista albero a quella nuova lista (scartando quella precedente).

7

Prova a camminare attraverso i nodi all'indietro. In questo modo l'indice non aumenta oltre la dimensione del nodo:

 
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

Questo è il metodo più efficiente. – Romias

+0

Vecchia domanda, ma +1 perché questo è il metodo più efficiente. – TimFoolery

+0

Rivisitando questo ... alcune modifiche lo renderebbero un po 'più veloce ... apportando le seguenti modifiche all'intestazione del ciclo: 'int ndx = nodes.Count-1' e' ndx> = 0' ti permetteranno per evitare il -1 che si verifica in ogni passaggio attraverso il ciclo. Nel grande schema delle cose, alcune sottrazioni extra non significheranno molto, ma ehi ... perché no? – TimFoolery

3

Se si desidera eseguire in modo efficiente, è necessario tenere traccia dei nodi controllati man mano che vengono controllati. Archiviare i nodi dell'albero controllati in un elenco (e rimuoverli come sono deselezionati).

Se si dispone di una chiave univoca e un sacco di nodi per tenere traccia di si potrebbe considerare un dizionario pure. Ma se hai a che fare solo con il 10-50 probabilmente non farai una grande differenza.

Quindi, anziché eseguire il ciclo attraverso l'intero albero, si passa semplicemente attraverso il (più piccolo) elenco di nodi.

Problemi correlati