Vorgehensweise: Durchlaufen aller Knoten eines TreeView-Steuerelements in Windows Forms
Manchmal ist es sinnvoll, alle Knoten in einem TreeView-Steuerelement in Windows Forms zu untersuchen, um Berechnungen mit den Knotenwerten durchzuführen. Dieser Vorgang kann über eine rekursive Methode (rekursive Prozedur in VB.NET) ausgeführt werden, die alle Knoten der einzelnen Auflistungen der Struktur durchläuft.
Jedes TreeNode-Objekt in einer Strukturansicht verfügt über Eigenschaften, mit denen Sie durch die Strukturansicht navigieren können: FirstNode, LastNode, NextNode, PrevNode und Parent. Der Wert der Parent-Eigenschaft ist der übergeordnete Knoten des aktuellen Knotens. Die untergeordneten Knoten des aktuellen Knotens werden, falls vorhanden, in der Nodes-Eigenschaft aufgelistet. Das TreeView-Steuerelement selbst umfasst die TopNode-Eigenschaft, die der Stammknoten der gesamten Strukturansicht ist.
Rekursive Vorgehensweise
Bei der rekursiven Vorgehensweise wird eine Methode verwendet, die einen Strukturknoten verarbeitet. Die gleiche Methode wird dann für jeden untergeordneten Knoten aufgerufen. Dies wird solange wiederholt, bis jeder Knoten in der Struktur verarbeitet wurde. Der Nachteil dieser Vorgehensweise besteht darin, dass bei einer umfangreichen Struktur u. U. ein Stapelüberlauffehler auftreten kann und der verfügbare Arbeitsspeicher nicht ausreicht.
Im folgenden Beispiel wird veranschaulicht, wie die Text-Eigenschaft jedes TreeNode-Objekts gelesen wird:
private void PrintRecursive(TreeNode treeNode)
{
// Print the node.
System.Diagnostics.Debug.WriteLine(treeNode.Text);
MessageBox.Show(treeNode.Text);
// Visit each node recursively.
foreach (TreeNode tn in treeNode.Nodes)
{
PrintRecursive(tn);
}
}
// Call the procedure using the TreeView.
private void CallRecursive(TreeView treeView)
{
// Print each node recursively.
foreach (TreeNode n in treeView.Nodes)
{
//recursiveTotalNodes++;
PrintRecursive(n);
}
}
Private Sub PrintRecursive(n As TreeNode)
System.Diagnostics.Debug.WriteLine(n.Text)
MessageBox.Show(n.Text)
Dim aNode As TreeNode
For Each aNode In n.Nodes
PrintRecursive(aNode)
Next
End Sub
' Call the procedure using the top nodes of the treeview.
Private Sub CallRecursive(aTreeView As TreeView)
Dim n As TreeNode
For Each n In aTreeView.Nodes
PrintRecursive(n)
Next
End Sub
private:
void PrintRecursive(TreeNode^ treeNode)
{
// Print the node.
System::Diagnostics::Debug::WriteLine(treeNode->Text);
MessageBox::Show(treeNode->Text);
// Print each node recursively.
System::Collections::IEnumerator^ myNodes = (safe_cast<System::Collections::IEnumerable^>(treeNode->Nodes))->GetEnumerator();
try
{
while (myNodes->MoveNext())
{
TreeNode^ tn = safe_cast<TreeNode^>(myNodes->Current);
PrintRecursive(tn);
}
}
finally
{
delete(myNodes);
}
}
// Call the procedure using the TreeView.
void CallRecursive(TreeView^ treeView)
{
// Print each node recursively.
TreeNodeCollection^ nodes = treeView->Nodes;
System::Collections::IEnumerator^ myNodes = (safe_cast<System::Collections::IEnumerable^>(nodes))->GetEnumerator();
try
{
while (myNodes->MoveNext())
{
TreeNode^ n = safe_cast<TreeNode^>(myNodes->Current);
PrintRecursive(n);
}
}
finally
{
delete(myNodes);
}
}
Nicht rekursive Vorgehensweise
Im folgenden Beispiel handelt es sich um eine alternative iterative Vorgehensweise zum Durchlaufen der Knoten der Struktur unter Verwendung einer Queue<T>-Auflistung. Diese Vorgehensweise folgt nicht der hierarchischen Beziehung eines Knotens, um zu gewährleisten, dass jeder Knoten ausgegeben wird. Wenn Sie jeden Strukturknoten und dessen untergeordneten Elemente verarbeiten möchten, verwenden Sie zuerst die Stack<T>-Auflistung.
private void PrintNonRecursive(TreeNode treeNode)
{
if (treeNode != null)
{
//Using a queue to store and process each node in the TreeView
Queue<TreeNode> staging = new Queue<TreeNode>();
staging.Enqueue(treeNode);
while (staging.Count > 0)
{
treeNode = staging.Dequeue();
// Print the node.
System.Diagnostics.Debug.WriteLine(treeNode.Text);
MessageBox.Show(treeNode.Text);
foreach (TreeNode node in treeNode.Nodes)
{
staging.Enqueue(node);
}
}
}
}
// Call the procedure using the TreeView.
private void CallNonRecursive(TreeView treeView)
{
// Print each node.
foreach (TreeNode n in treeView.Nodes)
{
PrintNonRecursive(n);
}
}
Private Sub PrintNonrecursive(n As TreeNode)
If n IsNot Nothing Then
Dim staging As Queue(Of TreeNode) = New Queue(Of TreeNode)
staging.Enqueue(n)
While staging.Count > 0
n = staging.Dequeue()
'Print the node.
System.Diagnostics.Debug.WriteLine(n.Text)
MessageBox.Show(n.Text)
Dim node As TreeNode
For Each node In n.Nodes
staging.Enqueue(node)
Next
End While
End If
End Sub
Private Sub CallNonRecursive(aTreeView As TreeView)
Dim n As TreeNode
For Each n In aTreeView.Nodes
PrintNonrecursive(n)
Next
End Sub
private:
void PrintNonRecursive(TreeNode^ treeNode)
{
//Using a queue to store and process each node in the TreeView
Queue^ staging = gcnew Queue();
staging->Enqueue(treeNode);
while (staging->Count > 0)
{
treeNode = safe_cast<TreeNode^>(staging->Dequeue());
// Print the node.
System::Diagnostics::Debug::WriteLine(treeNode->Text);
MessageBox::Show(treeNode->Text);
System::Collections::IEnumerator^ children = (safe_cast<System::Collections::IEnumerable^>(treeNode->Nodes))->GetEnumerator();
try
{
while (children->MoveNext())
{
staging->Enqueue(children->Current);
}
}
finally
{
delete(children);
}
}
// Print the node.
System::Diagnostics::Debug::WriteLine(treeNode->Text);
MessageBox::Show(treeNode->Text);
// Print each node recursively.
System::Collections::IEnumerator^ myNodes = (safe_cast<System::Collections::IEnumerable^>(treeNode->Nodes))->GetEnumerator();
try
{
while (myNodes->MoveNext())
{
TreeNode^ tn = safe_cast<TreeNode^>(myNodes->Current);
PrintRecursive(tn);
}
}
finally
{
delete(myNodes);
}
}
// Call the procedure using the TreeView.
void CallNonRecursive(TreeView^ treeView)
{
// Print each node recursively.
TreeNodeCollection^ nodes = treeView->Nodes;
System::Collections::IEnumerator^ myNodes = (safe_cast<System::Collections::IEnumerable^>(nodes))->GetEnumerator();
try
{
while (myNodes->MoveNext())
{
TreeNode^ n = safe_cast<TreeNode^>(myNodes->Current);
PrintNonRecursive(n);
}
}
finally
{
delete(myNodes);
}
}
Weitere Informationen
.NET Desktop feedback