16

WinForms .NET アプリケーションに TreeView コントロールがあります。このコントロールには、複数のレベルの子ノードがあり、複数の子ノードを持つ子ノードがあり、深さが定義されていません。ユーザーが任意の親ノードを選択した場合 (ルート レベルである必要はありません)、その親ノードの下にあるすべてのノードのリストを取得するにはどうすればよいですか?

たとえば、私はこれから始めました:

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

問題は、このループの深さが定義されており、ノードが 3 レベル下に埋もれていることだけです。次にユーザーが親ノードを選択したときに、7 つのレベルがあるとしたら?

4

10 に答える 10

20

再帰を使用する

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
于 2008-10-07T05:10:35.767 に答える
13

これは、コアライブラリからこのタスクを実行するために使用するコードのスニペットです。
これにより、再帰を使用せずに、ノードを深さ優先または呼吸優先のいずれかにリストできます。これには、JITエンジンでスタックフレームを構築するオーバーヘッドがあります。その非常に高速です。

それを使用するには、単に行きます:

List< TreeNode > nodes = TreeViewUtils.FlattenDepth(tree);

申し訳ありませんが、VB.Netタグがあります。例をあげることはできませんが、きっとうまくいくと思います。

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;
    }
}
于 2009-02-26T13:01:08.053 に答える
13

これに使用する拡張メソッドがあります。

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;
        }
}

これはC#ですが、VBから参照したり、変換したりすることができます。

于 2009-06-09T09:33:11.583 に答える
13

これを行うには再帰関数が必要です[または同等のループですが、再帰バージョンの方が簡単です] - 擬似コード:

function outputNodes(Node root)
    writeln(root.Text)
    foreach(Node n in root.ChildNodes)
        outputNodes(n)
    end
end
于 2008-10-07T05:05:25.213 に答える
3
nodParent As TreeNode
'nodParent = your parent Node
tvwOpt.Nodes.Find(nodParent.Name, True)

それでおしまい

于 2010-06-19T12:07:11.630 に答える
2

VB.Net結果として、コードを次のように変換しました。

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
于 2009-06-09T09:22:23.943 に答える
1

Jop のコードを使用し、TreeNodes を保持したまま (.tag、.name、.checked、または .text プロパティを使用できるように) 再帰アプローチを実行したい場合は、ここに私のバージョンがあります。

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
于 2015-10-06T05:19:18.643 に答える
1

通常、指定されたノードで値を取得することは、プログラマにとって興味深いことです。これは次のように取得できます。texbox1 という名前の TextBox コントロールと、treeview1 という名前の TreeView コントロールがあると仮定します。以下は、ノード レベル 0 のテキストの値を返します。

textbox1.Text = treeview1.nodes(0).Text.ToString()
于 2016-12-14T03:50:42.860 に答える
0

in .Net WindowsForm TreeView にはFind()、オプションの flag を持つメソッドがあります'searchAllChildren'

代わりにasp.netにはありません。同じ結果を得るには、これを使用します(キースの回答に似ていますが、入力ではTreeViewを使用します)

public static IEnumerable<TreeNode> DescendantNodes2(this TreeView input)
{
    foreach (TreeNode node in input.Nodes)
    {
        yield return node;
        foreach (var subnode in node.DescendantNodes())
            yield return subnode;
    }
}
private static IEnumerable<TreeNode> DescendantNodes(this TreeNode input)
{
    foreach (TreeNode node in input.ChildNodes)
    {
        yield return node;
        foreach (var subnode in node.DescendantNodes())
            yield return subnode;
    }
}
于 2020-06-26T06:19:48.190 に答える