Accéder à tous les nœuds dans TreeView Control

J’ai un contrôle TreeView avec un ensemble de nœuds et de nœuds enfants. Par exemple:

ROOT a A, B, C.

A a a1, a2, a3, puis a1, a2 contient également des nœuds comme x1, x2, x3, etc. Comme cela, il y a beaucoup de sous-noeuds. Je sais qu’il est possible d’utiliser des boucles avec une boucle for.

Je veux juste accéder à tous les nœuds du contrôle TreeView utilisant une ou deux boucles for.

Existe-t-il un algorithme pour cela ou existe-t-il un autre moyen?

Une autre question: est-il possible d’avoir le chemin d’un nœud d’arbre dans un object ou dans une chaîne en utilisant des fonctions de bibliothèque? Par exemple:

 ssortingng S = TreeView1.Nodes[i].Nodes[j].Nodes 

N’utilisez pas de boucles nestedes, mais optez pour une solution récursive telle que:

 void ListNodes( TreeNode node ) { foreach( var subnode in node.Nodes ) { ListNodes( subnode ); } // Print out node } 

Appelez cette fonction pour votre nœud racine.

Pour votre question supplémentaire: vérifiez la propriété FullPath .

Vous pouvez utiliser une fonction récursive pour parcourir l’arbre entier:

 private void Traverse(TreeNodeCollection nodes) { foreach (TreeNode node in nodes) { Console.WriteLine("{0} -> {1}", node.Name, node.FullPath); Traverse(node.Nodes); } } 

Vous pouvez ensuite appeler cela en utilisant:

 Traverse(treeView.Nodes); 

et il marchera d’abord sur toute la profondeur de l’arbre (c’est-à-dire qu’il descendra aussi profondément que possible avant de passer au frère ou à la soeur suivant). Passer dans la collection Nodes signifie que ce code traitera des arbres ayant plusieurs nœuds racine.

L’exemple de code ci-dessus affichera le nom du nœud ainsi que le chemin complet de ce nœud dans l’arborescence.

Je ne suis pas le plus grand fan de récursion, mais il semble que vous deviez l’utiliser. J’ai vu un exemple astucieux de mélange de récursivité en ligne avec un iterator.

  private int GetLevels(TreeNodeCollection treeNodes) { int level = 0; foreach (TreeNode node in TreeTopDown(treeNodes)) { int i = node.Level; if (i > level) level = i; } return level; } //TopDown Iterator private IEnumerable TreeTopDown(TreeNodeCollection treeNodes) { foreach (TreeNode node in treeNodes) { yield return node; foreach (TreeNode subNode in TreeTopDown(node.Nodes)) yield return subNode; } } //BottomUp Iterator private IEnumerable TreeBottomUp(TreeNodeCollection treeNodes) { foreach (TreeNode node in treeNodes) { foreach (TreeNode subNode in TreeBottomUp(node.Nodes)) yield return subNode; yield return node; } } 

Vous pouvez créer une méthode d’extension qui renvoie une List .

Méthode d’extension des descendants

 using System.Linq; using System.Windows.Forms; using System.Collections.Generic; public static class Extensions { public static List Descendants(this TreeView tree) { var nodes = tree.Nodes.Cast(); return nodes.SelectMany(x => x.Descendants()).Concat(nodes).ToList(); } public static List Descendants(this TreeNode node) { var nodes = node.Nodes.Cast().ToList(); return nodes.SelectMany(x => Descendants(x)).Concat(nodes).ToList(); } } 

Pour obtenir tous les nœuds d’un TreeView

 var nodes = this.treeView1.Descendants(); 

Pour obtenir tous les nœuds enfants d’un nœud

 var nodes = this.treeView1.Nodes[0].Descendants(); 

Vous pouvez également utiliser linq pour effectuer une recherche entre les nœuds.

Je sais que ce thread est assez ancien et que ma méthode ne réduit pas exactement la récursion . Elle est peut-être un peu plus lente, mais mon code est un peu plus propre.

J’utilise une méthode d’extension pour IEnumarable<> pour aplatir n’importe quel arbre (pas uniquement les nœuds TreeView):

 public static IEnumerable Flatten( this IEnumerable rootNodes, Func> childrenFunction) { return rootNodes.SelectMany( child => new[] { child } .Concat((childrenFunction(child) ?? Enumerable.Empty()) .Flatten(childrenFunction))); } 

J’utilise ensuite cette méthode pour obtenir tous les nœuds de l’arbre:

 IEnumerable allNodes = treeView1.Nodes.Cast() .Flatten(n => n.Nodes.Cast()); 

Vous pouvez utiliser Queue comme ce que j’avais fait dans mon application:

 List nodes = new List(); Queue queue = new Queue(); // // first insert all the root nodes into the queue. // foreach(TreeNode root in tree.Nodes) { queue.Enqueue(root); } 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); } } } } 

Le code suivant est utilisé pour parcourir les nœuds d’un TreeView et renvoyer uniquement les nœuds feuilles:

 private IEnumerable LeafNodes(TreeNode root) { Stack stack = new Stack(); stack.Push(root); while (stack.Count > 0) { TreeNode current = stack.Pop(); if (current.Nodes.Count == 0) { yield return current; } else { foreach (TreeNode child in current.Nodes) { stack.Push(child); } } } } 

Je l’utilise pour accéder aux noms de fichiers dans une arborescence de type explorateur:

 private void LogFileNames() { //There may be more than one node at root level foreach (TreeNode rootNode in FileTreeView.Nodes) { //Print only filenames, not directories foreach (TreeNode leafNode in LeafNodes(rootNode)) { Logger.Info(leafNode.Text); } } }