DataGridを階層化して表示するには
● DataGridを階層化して表示するサンプル

図 DataGridを階層化して表示するサンプル
このサンプルは、仕入先の取扱商品を階層化してDataGridに表示します。仕入先の左側に表示されているプラス(+)、マイナス(-)のリンクボタンをクリックすると取扱商品が表示/非表示に切り替わります。このサンプルでは、2階層のデータを表示していますが3階層、4階層のデータを表示することもできます。
このサンプルでは、以下のノウハウを習得することができます。
▲ DataGridのButtonColumnの使い方
▲ ButtonColumnとOnItemCommandイベントの使い方
▲ ButtonColumnのTextプロパティをランタイム時に書き換える方法
▲ DataGridのItemsコレクションのCountプロパティの使い方
▲ DataGridのItemsコレクションのVisibleプロパティの使い方
▲ DataGridのItemsコレクションのBackColorプロパティの使い方
▲ ItemsのCellsコレクション、Controls()コレクションの使い方
サンプルの行134-171では、DataGridを定義しています。行143では、DataGirdにOnItemCommandイベントを登録しています。このイベントでは、取扱商品の表示/非表示を切り替えます。行151-170の<Columns>…</Columns>では、ButtonColumn、BoundColumnでプラス、マイナスのリンクボタン、仕入先テーブルの仕入先名、商品テーブルの商品名、単位、単価を表示しています。行152-154のButtonColumnでは、プラス、マイナスのボタンを表示しています。プラス(+)記号は、取扱商品が非表示状態になっていることを意味します。マイナス(-)記号は、取扱商品が表示状態になっていることを意味します。ButtonColumnのButtonTypeプロパティを省略するとLinkButtonが採用されます。行155-158のBoundColumnでは、仕入先テーブルの仕入先名をバインドしています。行159-169のBoundColumnでは、商品テーブルの商品名、単位、単価をバインドしています。商品テーブルのカラムには、仕入先の取扱商品のみ表示されます。
134: <asp:DataGrid
id="dgrdSuppliers" runat="server"
::::
142:
AutoGenerateColumns="False"
143:
OnItemCommand="dgrdSuppliers_ItemCommand">
::::
151: <Columns>
152: <asp:ButtonColumn Text="*"
CommandName="ExpandSupplier">
154:
</asp:ButtonColumn>
155: <asp:BoundColumn DataField="CompanyName"
ReadOnly="True"
156:
HeaderText="仕入先" >
158:
</asp:BoundColumn>
159: <asp:BoundColumn DataField="ProductName"
HeaderText="商品" >
161:
</asp:BoundColumn>
162: <asp:BoundColumn DataField="QuantityPerUnit"
HeaderText="単位" >
164:
</asp:BoundColumn>
165: <asp:BoundColumn DataField="UnitPrice" HeaderText="単価"
166:
DataFormatString="{0:N0}">
169:
</asp:BoundColumn>
170:
</Columns>
171: </asp:DataGrid>
Page_Load()イベントでは、ページが最初にロードされたときにSub LoadResults()を呼び出してDataGridにDataTableをバインドしています。
7: Sub Page_Load()
8: If Not IsPostBack Then
9: LoadResults()
10: End If
11: End Sub
Sub LoadResults()の行14-16では、仕入先テーブルと商品テーブルのレコードを抽出するSQLを生成しています。行21では、DataTable(“Results”)を生成しています。ここで生成したDataTableは、DataGridにバインドして表示します。行26-31のWith…End Withでは、DataTableのResultsに仕入先名、商品名、単位、単価のカラムを追加しています。
行33-36では、仕入先テーブルと商品テーブルからレコードを抽出してDataSetに格納しています。行38-41のWith…End Withでは、仕入先テーブルと商品テーブルのリレーションを設定しています。仕入先テーブルと商品テーブルは、仕入先IDで結合します。DataSetには、SupplierProductの名称でDataRelationが追加されます。
行43-54のFor…Nextでは、仕入先のDataTableのRo
行47-53のFor…Nextでは、DataRowのGetChildRo
行56-57では、DataGridのDataSourceプロパティにResultsのDataTableを設定して、DataBind()メソッドでバインドしています。行58では、Sub SetHierarchical()を呼び出しています。
13: Sub LoadResults()
14: Dim strSqlSuppliers As String =
"Select * From Suppliers Where SupplierID <= 5;"
15: Dim strSqlProducts As String =
"Select * From Products " & _
16: "Where SupplierID
Between 1 And 5;"
17: Dim con As New OleDbConnection( _
18:
ConfigurationSettings.AppSettings("conStringNw"))
19: Dim da As OleDbDataAdapter
20: Dim ds As New DataSet()
21: Dim dt As DataTable = New
DataTable("Results")
22: Dim dr As DataRow
23: Dim SupplierRow As DataRow
24: Dim ProductRow As DataRow
25:
26: With dt
27:
.Columns.Add("CompanyName", GetType(System.String))
28:
.Columns.Add("ProductName", GetType(System.String))
29:
.Columns.Add("QuantityPerUnit", GetType(System.String))
30:
.Columns.Add("UnitPrice", GetType(System.Decimal))
31: End With
32:
33: da = New
OleDbDataAdapter(strSqlSuppliers, con)
34: da.Fill(ds,"Suppliers")
35: da.SelectCommand = New
OleDbCommand(strSqlProducts, con)
36: da.Fill(ds,"Products")
37:
38: With ds
39: .Relations.Add("SupplierProduct",
.Tables("Suppliers").Columns("SupplierID"), _
40:
.Tables("Products").Columns("SupplierID"))
41: End With
42:
43: For Each SupplierRow In
ds.Tables("Suppliers").Ro
44: dr = dt.NewRow()
45: dr("CompanyName")
= SupplierRow("CompanyName")
46: dt.Ro
47: For Each ProductRow In
SupplierRow.GetChildRo
48: dr =
dt.NewRow()
49:
dr("ProductName") = ProductRow("ProductName")
50:
dr("QuantityPerUnit") =
ProductRow("QuantityPerUnit")
51:
dr("UnitPrice") = ProductRow("UnitPrice")
52: dt.Ro
53: Next
54: Next
55:
56: dgrdSuppliers.DataSource = dt
57: dgrdSuppliers.DataBind()
58: SetHierarchical(False)
59: End Sub
Sub SetHierarchical()では、子アイテムを表示/非表示にします。行64-86のFor...Nextでは、DataGridのすべてのアイテムを検索して親アイテム(仕入先)と子アイテム(取扱商品)の各種プロパティを設定しています。
行66-74は、引数にTrue(Expanded)が指定されているときに実行されます。カレントのアイテムが子アイテム(取扱商品)のときは、そのアイテムを表示します。子アイテムの行は、仕入先のカラムに空白( )が格納されています。行67では、子アイテムのVisibleプロパティにTrueを設定して表示しています。行68では、子アイテムのLinkButtonのVisibleプロパティにFalseを設定して非表示にしています。行70-73は、カレントアイテムが親アイテム(仕入先)のときに実行されます。行70では、LinkButtonのTextプロパティにマイナス(-)を設定しています。行71では、LinkButtonのCssClassプロパティにCSSのクラス名PlusMinusを設定しています。行72では、親アイテムの背景色を小麦色(Wheat)に設定しています。行73では、LinkButtonの背景色を黄褐色(Tan)に設定しています。
行76-84は、引数にFalse(Collapsed)が指定されているときに実行されます。カレントのアイテムが子アイテム(取扱商品)のときは、そのアイテムを非表示にします。行77では、子アイテムのVisibleプロパティにFalseを設定して非表示にしています。行78では、子アイテムのLinkButtonのVisibleプロパティにFalseを設定して非表示にしています。行80-83は、カレントアイテムが親アイテム(仕入先)のときに実行されます。行80では、LinkButtonのTextプロパティにプラス(+)を設定しています。行81では、LinkButtonのCssClassプロパティにCSSのクラス名PlusMinusを設定しています。行82では、親アイテムの背景色を小麦色(Wheat)に設定しています。行83では、LinkButtonの背景色を黄褐色(Tan)に設定しています。
61: Sub SetHierarchical(bExpanded As Boolean)
::::
64: For i=0 To
dgrdSuppliers.Items.Count - 1
65: If bExpanded Then ‘ 子アイテムの表示
66: If
dgrdSuppliers.Items(i).Cells(1).Text = " " Then ' カレントが子アイテム
67:
dgrdSuppliers.Items(i).Visible = True ' 子アイテムを表示
68:
dgrdSuppliers.Items(i).Cells(0).Controls(0).Visible = False ' LinkButtonを非表示
69: Else ' カレントが親アイテム
70:
CType(dgrdSuppliers.Items(i).Cells(0).Controls(0), LinkButton).Text =
"-"
71:
CType(dgrdSuppliers.Items(i).Cells(0).Controls(0), LinkButton).CssClass
= "PlusMinus"
72:
dgrdSuppliers.Items(i).BackColor = Color.Wheat ‘ 子アイテムの背景色設定
73:
dgrdSuppliers.Items(i).Cells(0).BackColor = Color.Tan ‘ LinkButtonの背景色設定
74: End If
75: Else ' 子アイテムの非表示
76: If
dgrdSuppliers.Items(i).Cells(1).Text = " " Then ' カレントが子アイテム
77:
dgrdSuppliers.Items(i).Visible = False ' 子アイテムを非表示
78:
dgrdSuppliers.Items(i).Cells(0).Controls(0).Visible = False ' LinkButtonを非表示
79: Else ' カレントが親アイテム
80:
CType(dgrdSuppliers.Items(i).Cells(0).Controls(0), LinkButton).Text =
"+"
81:
CType(dgrdSuppliers.Items(i).Cells(0).Controls(0), LinkButton).CssClass
= "PlusMinus"
82:
dgrdSuppliers.Items(i).BackColor = Color.Wheat ‘ 子アイテムの背景色設定
83:
dgrdSuppliers.Items(i).Cells(0).BackColor = Color.Tan ‘ LinkButtonの背景色設定
84: End If
85: End If
86: Next
87: End Sub
DataGridからLinkButton(+/-)をクリックすると、DataGridのOnItemCommandイベントが発生します。このイベントでは、子アイテムを表示/非表示にします。行92ではCommandNameプロパティを参照して、+/-のLinkButtonがクリックされたかチェックしています。行95-103は、LinkButtonがマイナス(-)のときに実行されます。行95-101のDo While…Loopでは、子アイテムのVisibleプロパティをFalseに設定して非表示にしています。行103では、LinkButtonのTextプロパティをマイナスからプラスに切り替えています。
行106-116は、LinkButtonがプラス(+)のときに実行されます。行106-114のDo While…Loopでは、子アイテムのVisibleプロパティにTrueを設定して表示しています。行116では、LinkButtonのTextプロパティをプラスからマイナスに切り替えています。
89: Sub dgrdSuppliers_ItemCommand(s As Object, e As
DataGridCommandEventArgs)
90: Dim i As Integer =
e.Item.ItemIndex + 1
91:
92: If e.CommandName =
"ExpandSupplier" Then
93: If CType(e.Item.Cells(0).Controls(0),
LinkButton).Text = "-" Then
95: Do While
dgrdSuppliers.Items(i).Cells(1).Text = " "
96:
dgrdSuppliers.Items(i).Visible = False
97:
i += 1
98:
If i >= dgrdSuppliers.Items.Count Then
99:
Exit Do
100:
End If
101: Loop
103:
CType(e.Item.Cells(0).Controls(0), LinkButton).Text = "+"
104:
Else
106: Do While
dgrdSuppliers.Items(i).Cells(1).Text = " "
107:
If dgrdSuppliers.Items(i).Cells(2).Text <> " "
Then
108:
dgrdSuppliers.Items(i).Visible = True
109:
End If
110:
i += 1
111:
If i >= dgrdSuppliers.Items.Count Then
112:
Exit Do
113:
End If
114: Loop
116:
CType(e.Item.Cells(0).Controls(0), LinkButton).Text = "-"
117:
End If
118: End If