DataGridを階層化して表示するには

 

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

 

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

 

このサンプルは、仕入先の取扱商品を階層化してDataGridに表示します。仕入先の左側に表示されているプラス(+)、マイナス(-)のリンクボタンをクリックすると取扱商品が表示/非表示に切り替わります。このサンプルでは、2階層のデータを表示していますが3階層、4階層のデータを表示することもできます。

 

このサンプルでは、以下のノウハウを習得することができます。

 

  DataGridButtonColumnの使い方

  ButtonColumnOnItemCommandイベントの使い方

  ButtonColumnTextプロパティをランタイム時に書き換える方法

  DataGridItemsコレクションのCountプロパティの使い方

  DataGridItemsコレクションのVisibleプロパティの使い方

  DataGridItemsコレクションのBackColorプロパティの使い方

  ItemsCellsコレクション、Controls()コレクションの使い方

 

サンプルの行134-171では、DataGridを定義しています。行143では、DataGirdOnItemCommandイベントを登録しています。このイベントでは、取扱商品の表示/非表示を切り替えます。行151-170<Columns>…</Columns>では、ButtonColumnBoundColumnでプラス、マイナスのリンクボタン、仕入先テーブルの仕入先名、商品テーブルの商品名、単位、単価を表示しています。行152-154ButtonColumnでは、プラス、マイナスのボタンを表示しています。プラス()記号は、取扱商品が非表示状態になっていることを意味します。マイナス()記号は、取扱商品が表示状態になっていることを意味します。ButtonColumnButtonTypeプロパティを省略するとLinkButtonが採用されます。行155-158BoundColumnでは、仕入先テーブルの仕入先名をバインドしています。行159-169BoundColumnでは、商品テーブルの商品名、単位、単価をバインドしています。商品テーブルのカラムには、仕入先の取扱商品のみ表示されます。

 

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()を呼び出してDataGridDataTableをバインドしています。

 

  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-31With…End Withでは、DataTableResultsに仕入先名、商品名、単位、単価のカラムを追加しています。

 

33-36では、仕入先テーブルと商品テーブルからレコードを抽出してDataSetに格納しています。行38-41With…End Withでは、仕入先テーブルと商品テーブルのリレーションを設定しています。仕入先テーブルと商品テーブルは、仕入先IDで結合します。DataSetには、SupplierProductの名称でDataRelationが追加されます。

 

43-54For…Nextでは、仕入先のDataTableRowsコレクションからDataRowを取り出してDataTableResultsに追加しています。行44-46では、新規DataRowに仕入先名を設定してDataTable(“Results”)に追加しています。つまり、新規レコードを追加しています。このレコードは、DataGrid上では親アイテムとして表示されます。

 

47-53For…Nextでは、DataRowGetChildRows()メソッドを使用して取扱商品のDataRowを生成してDataTable(”Results”)に追加しています。行48-52では、NewRow()メソッドで新規DataRowを生成して商品名、単位、単価を設定してからDataTableに追加しています。ここで追加したレコードは、DataGrid上では、子アイテムとして表示されます。

 

56-57では、DataGridDataSourceプロパティにResultsDataTableを設定して、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").Rows
 44:     dr = dt.NewRow()
 45:     dr("CompanyName") = SupplierRow("CompanyName")
 46:     dt.Rows.Add(dr)
 47:     For Each ProductRow In SupplierRow.GetChildRows("SupplierProduct")
 48:       dr = dt.NewRow()
 49:       dr("ProductName") = ProductRow("ProductName")
 50:       dr("QuantityPerUnit") = ProductRow("QuantityPerUnit")
 51:       dr("UnitPrice") = ProductRow("UnitPrice")
 52:       dt.Rows.Add(dr)
 53:     Next
 54:   Next
 55:
 56:   dgrdSuppliers.DataSource = dt
 57:   dgrdSuppliers.DataBind()
 58:   SetHierarchical(False)
 59: End Sub

 

Sub SetHierarchical()では、子アイテムを表示/非表示にします。行64-86For...Nextでは、DataGridのすべてのアイテムを検索して親アイテム(仕入先)と子アイテム(取扱商品)の各種プロパティを設定しています。

 

66-74は、引数にTrue(Expanded)が指定されているときに実行されます。カレントのアイテムが子アイテム(取扱商品)のときは、そのアイテムを表示します。子アイテムの行は、仕入先のカラムに空白(&nbsp;)が格納されています。行67では、子アイテムのVisibleプロパティにTrueを設定して表示しています。行68では、子アイテムのLinkButtonVisibleプロパティにFalseを設定して非表示にしています。行70-73は、カレントアイテムが親アイテム(仕入先)のときに実行されます。行70では、LinkButtonTextプロパティにマイナス(-)を設定しています。行71では、LinkButtonCssClassプロパティにCSSのクラス名PlusMinusを設定しています。行72では、親アイテムの背景色を小麦色(Wheat)に設定しています。行73では、LinkButtonの背景色を黄褐色(Tan)に設定しています。

 

76-84は、引数にFalse(Collapsed)が指定されているときに実行されます。カレントのアイテムが子アイテム(取扱商品)のときは、そのアイテムを非表示にします。行77では、子アイテムのVisibleプロパティにFalseを設定して非表示にしています。行78では、子アイテムのLinkButtonVisibleプロパティにFalseを設定して非表示にしています。行80-83は、カレントアイテムが親アイテム(仕入先)のときに実行されます。行80では、LinkButtonTextプロパティにプラス(+)を設定しています。行81では、LinkButtonCssClassプロパティに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 = "&nbsp;" 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 = "&nbsp;" 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(+/-)をクリックすると、DataGridOnItemCommandイベントが発生します。このイベントでは、子アイテムを表示/非表示にします。行92ではCommandNameプロパティを参照して、+/-LinkButtonがクリックされたかチェックしています。行95-103は、LinkButtonがマイナス(-)のときに実行されます。行95-101Do While…Loopでは、子アイテムのVisibleプロパティをFalseに設定して非表示にしています。行103では、LinkButtonTextプロパティをマイナスからプラスに切り替えています。

 

106-116は、LinkButtonがプラス(+)のときに実行されます。行106-114Do While…Loopでは、子アイテムのVisibleプロパティにTrueを設定して表示しています。行116では、LinkButtonTextプロパティをプラスからマイナスに切り替えています。

 

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 = "&nbsp;"
 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 = "&nbsp;"
107:         If dgrdSuppliers.Items(i).Cells(2).Text <> "&nbsp;" 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

 

ASP.NET DataGridのホームへ戻る