Pregunta

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

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

Incluso si uno utilizara dos pases: primero se crea una lista de índices temporales y luego se elimina por índice en la segunda pasada: los índices cambiarían en cada eliminación, lo que invalidaría la integridad de la lista de índices.

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

Aquí hay un ejemplo de código que se ve bien, pero en realidad solo elimina 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 solo podar los nodos de un árbol que tiene dos niveles de profundidad).

¿Fue útil?

Solución

Esto eliminará los nodos después de enumerarlos, y se puede usar recursivamente para n niveles 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);
    }
}

Otros consejos

Intenta caminar a través de los nodos hacia atrás. De esa manera, su índice no aumentará más allá del tamaño de su 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...
}

Si desea hacerlo de manera eficiente, debe realizar un seguimiento de los nodos comprobados a medida que se verifican. Almacene los nodos de árbol marcados en una lista (y elimínelos a medida que no estén marcados).

Si tiene una clave única y MUCHOS nodos para realizar un seguimiento, también puede considerar un diccionario. Pero si solo estás tratando con 10-50, probablemente no hará una gran diferencia.

Luego, en lugar de recorrer todo el árbol, recorre la lista (más pequeña) de nodos.

Mientras estés iterando, puedes construir una nueva lista de elementos sin marcar y luego volver a enlazar tu vista de árbol a esa nueva lista (descartando la anterior).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top