tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルTREEVIEW の使い方
記事No9654
投稿日: 2009/12/01(Tue) 13:36
投稿者はや
TREEVIEW の使い方での質問です。

製品を構成する、部品情報が入ったデータがあります。
製品毎に使用する部品は違いますし、階層も違ってきます。
どのような末端部品が使用されているかを、見た目でわかりやすくするため、TreeViewの使用を考えて下ります。

製品例
製品A ---- 中間1 --- 部品1
        |
        ---中間2 --- 部品2
                  |
                  -- 部品3

製品B ---- 中間1 --- 部品1
        |
        ---中間3 --- 部品4
                  |
                  -- 部品5 --- 部品x  
                             |
                             -- 部品y

など、階層(NODE)が製品によって違う。
データベース上のデータは、部品の順番と、階層の項目がある
製品Bの例
順番  階層  品名
1       0      製品B
2       1      中間1
3       2      部品1
4       1      中間3
5       2      部品4
6       2      部品5
7       3      部品x
8       3      部品y
          
このようなデータを、TREEVIEWに展開した形で表示したいのですが、動的に階層を変化させる方法がわかりません。

いろいろ、検索しましたがエキスプローラーのように、下位層を表示させたい時に、NODEを追加し展開する方法は出てきたのですが、初めから展開させる方法は見つけることが出来ませんでした。

お手数をおかけいたしますが、よろしくお願いいたします。

[ツリー表示へ]
タイトルRe: TREEVIEW の使い方
記事No9655
投稿日: 2009/12/01(Tue) 13:49
投稿者YuO
> いろいろ、検索しましたがエキスプローラーのように、下位層を表示させたい時に、NODEを追加し展開する方法は出てきたのですが、初めから展開させる方法は見つけることが出来ませんでした。

最初からすべてを追加しておいて,ExpandAllメソッドを呼び出せばよいのでは?
MSDN: TreeView.ExpandAll メソッド (System.Windows.Forms)
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.treeview.expandall.aspx

[ツリー表示へ]
タイトルRe^2: TREEVIEW の使い方
記事No9656
投稿日: 2009/12/01(Tue) 14:00
投稿者はや
YuOさん、アドバイスありがとうございます。

質問の説明が悪かったですね。
ExpandAllメソッドで、全展開できることはわかっていたのですが、それ以前に「階層が不特定の部品情報をTREEVIEWにNODEの追加?する方法」がわかりません。

※ルートノードを追加したあと、ひとつ下の階層(子)はルートに対して「Nodes.Add」で追加すればよいのですが、さらにその下(孫)、さらに(ひ孫)・・・と、動的に増えて行き、最下位層まできたら、途中の(子)(孫)・・にもどって繰り返し追加する方法です。

TREEVIEWを使用するのは、初めてで根本的なことがわかっていません。

以上、よろしくお願いいたします。

[ツリー表示へ]
タイトルRe: TREEVIEW の使い方
記事No9657
投稿日: 2009/12/01(Tue) 15:31
投稿者魔界の仮面弁士
#Region "階層で管理される場合"
    Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
        Dim tbl As DataTable = GetSample1()
        If tbl.Rows.Count = 0 Then
            Return
        End If
        Dim maxLevel As Integer = CInt(tbl.Compute("MAX(層)", ""))
        Dim nodes(maxLevel + 1) As TreeNodeCollection
        nodes(0) = TreeView1.Nodes

        For Each row As DataRow In tbl.Rows
            Dim lv As Integer = CInt(row("層"))
            nodes(lv + 1) = nodes(lv).Add(row("ID").ToString(), row("名").ToString()).Nodes
        Next
        TreeView1.ExpandAll()
    End Sub

    Private Function GetSample1() As DataTable
        Dim tbl As New DataTable
        tbl.Columns.Add("ID", GetType(Integer))
        tbl.Columns.Add("層", GetType(Integer))
        tbl.Columns.Add("名", GetType(String))
        tbl.PrimaryKey = New DataColumn() {tbl.Columns("ID")}

        tbl.Rows.Add(1, 0, "製品A") '製品A
        tbl.Rows.Add(2, 1, "中間1") '┣中間1
        tbl.Rows.Add(3, 2, "部品1") '┃┗部品1
        tbl.Rows.Add(4, 1, "中間2") '┗中間2
        tbl.Rows.Add(5, 2, "部品2") ' ┣部品2
        tbl.Rows.Add(6, 2, "部品3") ' ┗部品3

        Return tbl
    End Function
#End Region


あらかじめ、データ内容の整合性を検査しておいてください。
第1階層が無いのに、第2階層が存在していた場合などは展開できません。

[ツリー表示へ]
タイトルRe^2: TREEVIEW の使い方
記事No9658
投稿日: 2009/12/01(Tue) 15:42
投稿者魔界の仮面弁士
今回のデータとは管理方法が異なりますが、このような実装パターンもあります。


#Region "親IDにて管理される場合"
    Private Sub Button2_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button2.Click
        Dim tbl As DataTable = GetSample2()
        Dim nodes As Dictionary(Of Integer, TreeNode) = ToDictionary(tbl.Rows)
        Dim rootNodes As TreeNodeCollection = TreeView1.Nodes
        For Each item As KeyValuePair(Of Integer, TreeNode) In nodes
            Dim parentNodes As TreeNodeCollection
            Dim parentID As Integer = CInt(item.Value.Tag("親"))
            If nodes.ContainsKey(parentID) Then
                parentNodes = nodes(parentID).Nodes
            Else
                parentNodes = rootNodes
            End If
            parentNodes.Add(item.Value)
        Next
        TreeView1.ExpandAll()
    End Sub

    Private Function ToDictionary(ByVal rows As DataRowCollection) As Dictionary(Of Integer, TreeNode)
        Dim nodes As New Dictionary(Of Integer, TreeNode)
        For Each row As DataRow In rows
            Dim node As New TreeNode(row("名").ToString())
            node.Tag = row
            nodes.Add(CInt(row("ID")), node)
        Next
        Return nodes
    End Function

    Private Function GetSample2() As DataTable
        Dim tbl As New DataTable
        tbl.Columns.Add("ID", GetType(Integer))
        tbl.Columns.Add("親", GetType(Integer))
        tbl.Columns.Add("名", GetType(String))
        tbl.PrimaryKey = New DataColumn() {tbl.Columns("ID")}

        tbl.Rows.Add(7, 0, "製品B")     '製品B
        tbl.Rows.Add(8, 7, "中間1")     '┣中間1
        tbl.Rows.Add(9, 8, "部品1")     '┃┗部品1
        tbl.Rows.Add(10, 7, "中間3")    '┗中間3
        tbl.Rows.Add(11, 10, "部品4")   ' ┣部品4
        tbl.Rows.Add(12, 10, "部品5")   ' ┗部品5
        tbl.Rows.Add(13, 12, "部品x")   '  ┣部品x
        tbl.Rows.Add(14, 12, "部品y")   '  ┗部品y

        Return tbl
    End Function
#End Region


こちらも、データ内容の整合性に注意してください。
第IDが自分の子孫ノードになっていた場合や、存在しないIDが
指定されていた場合、正しく展開できません。

[ツリー表示へ]
タイトルRe^2: TREEVIEW の使い方
記事No9659
投稿日: 2009/12/01(Tue) 16:02
投稿者はや
魔界の仮面弁士 さん、サンプルまで提供していただきありがとうございます。

早速、実践してみます。
 ※整合性は、例で示したデータを吐き出すプログラムにてチェック済です。


結果は、後ほど報告させていただきます。

[ツリー表示へ]
タイトルRe^2: TREEVIEW の使い方
記事No9661
投稿日: 2009/12/01(Tue) 16:38
投稿者はや
魔界の仮面弁士 さん ありがとうございます!

自分のソースにサンプルを引用し、思うように動きました!


>nodes(lv + 1) = nodes(lv).Add(row("ID").ToString(), row("名").ToString()).Nodes
この部分が、まったく自分の頭では想像できませんでした。

以前にも魔界の仮面弁士さんには助けていただいたことがあり、毎回的確なアドバイス(今回は答えそのものですが)ありがとうございます!

[ツリー表示へ]