2009-05-05 16 views
7

¿Cómo se puede iterar fácilmente a través de todos los nodos en un TreeView, examinar su propiedad Chequeada y luego eliminar todos los nodos marcados?Cómo eliminar eficientemente los elementos verificados de un TreeView?

Parece sencillo, pero se supone que no debe modificar una colección a través de la cual está iterando, eliminando la posibilidad de un bucle "foreach". (La llamada .Nodes.Remove está modificando la colección). Si se intenta, el efecto es que solo se eliminan aproximadamente la mitad de los nodos comprobados.

Incluso si tuviera que usar dos pasadas: primero creando una lista de índices temporales, y luego eliminando por índice en la segunda pasada - los índices cambiarían en cada eliminación, invalidando la integridad de la lista de índices.

Entonces, ¿cuál es la forma más eficiente de hacer esto?

Aquí es un ejemplo de código que se ve bien, pero en realidad sólo elimina aproximadamente la mitad de los nodos .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í, la intención es únicamente para podar los nodos de un árbol que es de dos niveles profundos.)

Respuesta

6

Esto eliminará los nodos después de enumerar ellos, y se puede utilizar de forma recursiva N capas de nodos.

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

Al iterar, podría construir una nueva lista de elementos no verificados y luego volver a vincular su vista de árbol a esa nueva lista (descartando la anterior).

7

Intenta caminar por los nodos hacia atrás. De esa manera su índice no aumenta más allá de su tamaño de los ganglios:

 
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

Este es el método más eficiente. – Romias

+0

Pregunta anterior, pero +1 por ser el método más eficiente. – TimFoolery

+0

Revisando esto ... algunas modificaciones lo harían ligeramente más rápido ... haciendo los siguientes cambios en el encabezado for-loop: 'int ndx = nodes.Count-1' y' ndx> = 0' le permitirán para evitar el -1 que ocurre en cada pasada a través del bucle. En el gran esquema de las cosas, algunas restas adicionales no significarán mucho en absoluto, pero oye ... ¿por qué no? – TimFoolery

3

Si desea hacerlo de manera eficiente, debe hacer un seguimiento de los nodos marcados a medida que se comprueban. Almacene los nodos de árboles marcados en una lista (y elimínelos ya que están desmarcados).

Si tiene una clave única y MUCHOS nodos para realizar un seguimiento, también podría considerar un diccionario. Pero si solo se trata de 10-50, probablemente no hará una gran diferencia.

Luego, en lugar de pasar por todo el árbol, simplemente recorre su lista (más pequeña) de nodos.

Cuestiones relacionadas