ejemplos - Cómo obtener una lista de todos los nodos secundarios en TreeView en.NET
treeview con checkbox c# (9)
Tengo un control TreeView en mi aplicación WinForms .NET que tiene múltiples niveles de childnodes que tienen childnodes con más childnodes, sin profundidad definida. Cuando un usuario selecciona un nodo padre (no necesariamente en el nivel raíz), ¿cómo puedo obtener una lista de todos los nodos beneficiarios de ese nodo padre?
Por ejemplo, comencé con esto:
Dim nodes As List(Of String)
For Each childNodeLevel1 As TreeNode In parentNode.Nodes
For Each childNodeLevel2 As TreeNode In childNodeLevel1.Nodes
For Each childNodeLevel3 As TreeNode In childNodeLevel2.Nodes
nodes.Add(childNodeLevel3.Text)
Next
Next
Next
El problema es que esta profundidad de bucle está definida y solo estoy obteniendo nodos enterrados en tres niveles. ¿Qué pasa si la próxima vez que el usuario selecciona un nodo padre, hay siete niveles?
Por lo general, obtener un valor en el nodo especificado es interesante para los programadores. Esto se puede obtener de la siguiente manera. Supongamos que tiene un control TextBox llamado texbox1 y un control TreeView llamado treeview1.Siguiente devolverá el valor del texto en el nivel 0 de los nodos.
textbox1.Text = treeview1.nodes(0).Text.ToString()
necesita una función recursiva para hacer esto [o un equivalente de bucle, pero la versión recursiva es más simple] - pseudocódigo:
function outputNodes(Node root)
writeln(root.Text)
foreach(Node n in root.ChildNodes)
outputNodes(n)
end
end
Aquí hay un fragmento de código que utilizo para realizar esta tarea desde mi biblioteca central. Le permite hacer una lista de los nodos, ya sea en profundidad primero o aliento primero sin el uso de recurrencia, que tiene la sobrecarga de la construcción de fotogramas de pila en el motor de JIT. Es muy rápido.
Para usarlo simplemente ve:
List <TreeNode> nodes = TreeViewUtils.FlattenDepth (árbol);
Lamento que seas VB, no puedo dar un ejemplo, pero estoy seguro de que lo resolverás.
public class TreeViewUtils
{
/// <summary>
/// This static utiltiy method flattens all the nodes in a tree view using
/// a queue based breath first search rather than the overhead
/// of recursive method calls.
/// </summary>
/// <param name="tree"></param>
/// <returns></returns>
public static List<TreeNode> FlattenBreath(TreeView tree) {
List<TreeNode> nodes = new List<TreeNode>();
Queue<TreeNode> queue = new Queue<TreeNode>();
//
// Bang all the top nodes into the queue.
//
foreach(TreeNode top in tree.Nodes) {
queue.Enqueue(top);
}
while(queue.Count > 0) {
TreeNode node = queue.Dequeue();
if(node != null) {
//
// Add the node to the list of nodes.
//
nodes.Add(node);
if(node.Nodes != null && node.Nodes.Count > 0) {
//
// Enqueue the child nodes.
//
foreach(TreeNode child in node.Nodes) {
queue.Enqueue(child);
}
}
}
}
return nodes;
}
/// <summary>
/// This static utiltiy method flattens all the nodes in a tree view using
/// a stack based depth first search rather than the overhead
/// of recursive method calls.
/// </summary>
/// <param name="tree"></param>
/// <returns></returns>
public static List<TreeNode> FlattenDepth(TreeView tree) {
List<TreeNode> nodes = new List<TreeNode>();
Stack<TreeNode> stack = new Stack<TreeNode>();
//
// Bang all the top nodes into the queue.
//
foreach(TreeNode top in tree.Nodes) {
stack.Push(top);
}
while(stack.Count > 0) {
TreeNode node = stack.Pop();
if(node != null) {
//
// Add the node to the list of nodes.
//
nodes.Add(node);
if(node.Nodes != null && node.Nodes.Count > 0) {
//
// Enqueue the child nodes.
//
foreach(TreeNode child in node.Nodes) {
stack.Push(child);
}
}
}
}
return nodes;
}
}
Tengo un método de extensión que uso para esto:
public static IEnumerable<TreeNode> DescendantNodes( this TreeNode input ) {
foreach ( TreeNode node in input.Nodes ) {
yield return node;
foreach ( var subnode in node.DescendantNodes() )
yield return subnode;
}
}
Es C #, pero podría ser referenciado desde VB o convertido a él.
nodParent As TreeNode
''nodParent = your parent Node
tvwOpt.Nodes.Find(nodParent.Name, True)
Eso es
Si alguien todavía quiere hacer el enfoque de recursión, usando el código de Jop y manteniendo los TreeNodes (para que pueda usar sus propiedades .tag, .name, .checked o .text) aquí está mi versión
Public Shared Function GetChildren(objTree As TreeView) As List(Of TreeNode)
Dim nodes As List(Of TreeNode) = New List(Of TreeNode)
For Each parentNode As TreeNode In objTree.Nodes
nodes.Add(parentNode)
GetAllChildren(parentNode, nodes)
Next
Return nodes
End Function
Public Shared Sub GetAllChildren(parentNode As TreeNode, nodes As List(Of TreeNode))
For Each childNode As TreeNode In parentNode.Nodes
nodes.Add(childNode)
GetAllChildren(childNode, nodes)
Next
End Sub
Usa recursión
Function GetChildren(parentNode as TreeNode) as List(Of String)
Dim nodes as List(Of String) = New List(Of String)
GetAllChildren(parentNode, nodes)
return nodes
End Function
Sub GetAllChildren(parentNode as TreeNode, nodes as List(Of String))
For Each childNode as TreeNode in parentNode.Nodes
nodes.Add(childNode.Text)
GetAllChildren(childNode, nodes)
Next
End Sub
Ik heb de code omgezet naar vb.net con dit als resultaat ... suc6
Public Function FlattenBreadth(ByVal tree As TreeView) As List(Of TreeNode)
Dim nodes As New List(Of TreeNode)
Dim queue As New Queue(Of TreeNode)
Dim top As TreeNode
Dim nod As TreeNode
For Each top In tree.Nodes
queue.Enqueue(top)
Next
While (queue.Count > 0)
top = queue.Dequeue
nodes.Add(top)
For Each nod In top.Nodes
queue.Enqueue(nod)
Next
End While
FlattenBreadth = nodes
End Function
El método de Adrian es increíble. Funciona bastante rápido y funcionó mejor que el enfoque de recursión. He hecho una traducción a VB. Aprendí mucho de eso. Espero que alguien todavía lo necesite.
Para usarlo simplemente:
Dim FlattenedNodes As List(Of TreeNode) = clTreeUtil.FlattenDepth(Me.TreeView1)
Aquí está el código, ¡SALUDOS! :
Public Class clTreeUtil
'''''' <summary>
'''''' This static utiltiy method flattens all the nodes in a tree view using
'''''' a queue based breath first search rather than the overhead
'''''' of recursive method calls.
'''''' </summary>
'''''' <param name="tree"></param>
'''''' <returns></returns>
Public Shared Function FlattenBreath(Tree As TreeView) As List(Of TreeNode)
Dim nodes As List(Of TreeNode) = New List(Of TreeNode)
Dim queue As Queue(Of TreeNode) = New Queue(Of TreeNode)
''''
'''' Bang all the top nodes into the queue.
''''
For Each top As TreeNode In Tree.Nodes
queue.Enqueue(top)
Next
While (queue.Count > 0)
Dim node As TreeNode = queue.Dequeue()
If node IsNot Nothing Then
''''
'''' Add the node to the list of nodes.
''''
nodes.Add(node)
If node.Nodes IsNot Nothing And node.Nodes.Count > 0 Then
''''
'''' Enqueue the child nodes.
''''
For Each child As TreeNode In node.Nodes
queue.Enqueue(child)
Next
End If
End If
End While
Return nodes
End Function
'''''' <summary>
'''''' This static utiltiy method flattens all the nodes in a tree view using
'''''' a stack based depth first search rather than the overhead
'''''' of recursive method calls.
'''''' </summary>
'''''' <param name="tree"></param>
'''''' <returns></returns>
Public Shared Function FlattenDepth(tree As TreeView) As List(Of TreeNode)
Dim nodes As List(Of TreeNode) = New List(Of TreeNode)
Dim stack As Stack(Of TreeNode) = New Stack(Of TreeNode)
''''
'''' Bang all the top nodes into the queue.
''''
For Each top As TreeNode In tree.Nodes
stack.Push(top)
Next
While (stack.Count > 0)
Dim node As TreeNode = stack.Pop()
If node IsNot Nothing Then
''''
'''' Add the node to the list of nodes.
''''
nodes.Add(node)
If node.Nodes IsNot Nothing And node.Nodes.Count > 0 Then
''''
'''' Enqueue the child nodes.
''''
For Each child As TreeNode In node.Nodes
stack.Push(child)
Next
End If
End If
End While
Return nodes
End Function
End Class