DataGridの複数行を一括して編集/更新するには
● DataGridの複数行を一括して編集/更新するサンプル

図 DataGridの複数行を一括して編集/更新するサンプル
このサンプルは、DataGridに表示されている複数行のレコードを一括して編集/更新することができます。DataGridのTextBoxに表示されているデータを編集したら一括更新ボタンをクリックしてデータベースに書き込みます。DataGridのアイテムが変更されている行は、黄色の背景色で表示されます。
このサンプルでは、以下のノウハウを習得することができます。
▲ DataGridのTemplateColumnでTextBoxを表示する方法
▲ DataGridのフッタにButtonを表示する方法
▲ DataGridのアイテムが変更されている行を黄色の背景色で表示する方法
▲ ArralyListのAdd(), Clear(), TrimToSize()メソッドの使い方
▲ NamingContainerの使い方
サンプルの行96-139では、DataGridを定義しています。行103では、OnItemDataBoundイベントを登録しています。このイベントは、DataGridのDataBind()メソッドを実行したときに発生します。行104では、OnItemCommandイベントを登録しています。このイベントは、フッタに配置されている一括更新ボタンをクリックしたときに発生します。行110-138の<Columns>…</Columns>では、TemplateColumnで商品区分テーブルの商品区分IDと商品区分名をバインドしています。
96: <asp:DataGrid id="dgrdCategories"
runat="server"
103:
OnItemDataBound="dgrdCategories_ItemDataBound"
104:
OnItemCommand="dgrdCategories_ItemCommand"
:::: >
110: <Columns>
::::
138:
</Columns>
139: </asp:DataGrid>
行111-120では、TemplateColumnで商品区分IDをバインドしています。行112-115のItemTemplateでは、LabelのTextプロパティに商品区分IDをバインドしています。行117-119のFooterTemplateでは、LabelのTextプロパティに「⇒」を設定して表示しています。
111: <asp:TemplateColumn
HeaderText="ID">
112:
<ItemTemplate>
113:
<asp:Label id="lblCategoryID" runat="server"
114:
Text='<%# Container.DataItem("CategoryID")
%>' />
115:
</ItemTemplate>
117:
<FooterTemplate>
118:
<asp:Label runat="server" Text="⇒" />
119:
</FooterTemplate>
120:
</asp:TemplateColumn>
行121-137のTemplateColumnでは、商品区分名をバインドしています。行122-128のItemTemplateでは、TextBoxのTextプロパティに商品区分名をバインドしています。行124では、OnTextChangedイベントを登録しています。このイベントは、TextBoxのデータを変更してフォーカスを他のコントロールに移動したときに発生します。OnTextChangedイベントでは、変更されてたレコードの商品区分IDをArrayListに格納します。行129-136のFooterTemplateでは、Buttonで一括更新ボタンを表示しています。行131では、CommandNameプロパティにUpdateAllを設定しています。一括更新ボタンをクリックすると、DataGridのOnItemCommandイベントが発生します。このイベントでは、CommandNameプロパティを参照してどのボタンがクリックされたかチェックして対応する処理を行います。
121: <asp:TemplateColumn
HeaderText="商品区分名">
122:
<ItemTemplate>
123:
<asp:TextBox id="txtCategoryName" runat="server"
124:
OnTextChanged="txtCategoryName_TextChanged"
125:
Text='<%#
Container.DataItem("CategoryName") %>'
126:
CssClass="txtShadow"
127:
MaxLength="30" />
128:
</ItemTemplate>
129:
<FooterTemplate>
130: <asp:Button id="btnUpdateAll" runat="server"
131:
CommandName="UpdateAll"
132:
Style="color:blue"
133:
Width="100%"
134:
ToolTip="複数行を一括して更新します!"
135:
Text="一括更新" />
136:
</FooterTemplate>
137:
</asp:TemplateColumn>
DataGridのTextBoxに表示されている商品区分名を変更してフォーカスを移動するとOnTextChangedイベントが発生します。このイベントでは、ArrayListに変更されたレコードの商品区分IDを格納しています。ArrayListに格納された商品区分IDは、一括更新ボタンをクリックしたときに使用します。行82では、TextBoxのNamingContainerからDataGridItemを取得しています。行83では、DataGridItemのFindControl()メソッドで商品区分IDのLabelを検索してTextプロパティの値を取得しています。行84-86では、ArrayListのContains()メソッドで商品区分IDがArrayListに格納されているか調べて、格納されていないときはAdd()メソッドで追加します。
81: Protected Sub txtCategoryName_TextChanged(s As
Object, e As EventArgs)
82: Dim dgi As DataGridItem =
CType(CType(s, Control).NamingContainer, DataGridItem)
83: Dim intCategoryID As Integer =
Int32.Parse(CType(dgi.FindControl("lblCategoryID"), Label).Text)
84: If Not
(marrCategoryList.Contains(intCategoryID)) Then
85:
marrCategoryList.Add(intCategoryID)
86: End If
87: End Sub
商品区分名が変更されているとき、TextBoxの背景色を黄色で表示するには、TextBoxにOnChangeイベントを登録してJavaScriptで背景色を書き換えます。TextBoxにブラウザで実行されるイベントを登録するには、TextBoxのAttributes.Add()メソッドを使用します。OnChangeイベントの登録は、DataGridのOnItemDataBoundイベントで行います。行73では、ItemのFindControl()メソッドでTextBoxを検索しています。行74-78では、TextBoxが見つかったか調べてOnChangeイベントを登録しています。OnItemDataBoundイベントは、DataGridのヘッダ、フッタにも適用されますので、FindControl()メソッドを実行したときはTextBoxが見つかったかチェックする必要があります。
72: Sub dgrdCategories_ItemDataBound(s As Object, e
As DataGridItemEventArgs)
73: Dim txtCategory As TextBox = e.Item.FindControl("txtCategoryName")
74: If Not (txtCategory Is Nothing)
Then
75: With txtCategory
76:
.Attributes.Add("onChange","this.style.backgroundColor='yellow'")
77: End With
78: End If
79: End Sub
DataGridから一括更新ボタンをクリックすると、OnItemCommandイベントが発生します。このイベントでは、ButtonのCommandNameプロパティを参照してどのボタンがクリックされたかチェックしています。一括更新ボタンをクリックしたときは、Sub dgrdCategories_UpdateAll()を呼び出します。
35: Sub dgrdCategories_ItemCommand(s As Object, e As
DataGridCommandEventArgs)
36: If e.CommandName = "UpdateAll"
Then
37:
dgrdCategories_UpdateAll()
38: End If
39: End Sub
Sub
dgrdCategories_UpdateAll()では、変更されたレコードを一括してデータベースに反映します。行42-43では、SQLのUpdateステートメントを生成しています。行44-45では、OleDbConnectionのインスタンスを生成しています。引数には、Web.configに登録されているデータベース接続情報を設定しています。
行52-65のFor…Nextループでは、DataGridのアイテムを検索して変更されているレコードを見つけたらデータベースに書き込んでいます。行53では、DataGridItemのFindControl()メソッドで商品区分IDのLabelを検索してTextプロパティの値を取得しています。行54-64のIf..End Ifでは、ArrayListのContains()メソッドで商品区分IDがArralyListに格納されているか調べています。行55では、DataGridItemのFindControl()メソッドで商品区分名のTextBoxを検索してTextプロパティから値を取得しています。行56-60では、OleDbCommandのインスタンスを生成してUpdateステートメントのパラメータに値を設定しています。行61-63では、OleDbCommandのExecuteNonQuery()メソッドでUpdateステートメントを実行してデータベースに書き込んでいます。
行66-67では、ArrayListのClear()メソッドですべての要素を消去して、TrimToSize()メソッドでメモリの所要量を少なくしています。行68では、Sub LoadData()を呼び出して商品区分テーブルのレコードを抽出してDataSetに格納しています。行69では、Sub BindDataGrid()を呼び出して、DataSetからDataTableを生成してDataGridにバインドしています。これで、一括更新されたレコードがDataGrid上に再表示されます。
41: Sub dgrdCategories_UpdateAll()
42: Dim strSQL As String =
"Update Categories Set CategoryName=@CategoryName " & _
43: "Where
CategoryID=@CategoryID"
44: Dim con As New OleDbConnection( _
45:
ConfigurationSettings.AppSettings("conStringNw"))
46: Dim cmd As OleDbCommand
47:
48: Dim dgi As DataGridItem
49: Dim intCategoryID As Integer
50:
Dim strCategoryName As String
51:
52: For Each dgi in
dgrdCategories.Items
53: intCategoryID =
Int32.Parse(CType(dgi.FindControl("lblCategoryID"), Label).Text)
54: If
marrCategoryList.Contains(intCategoryID) Then
55:
strCategoryName = CType(dgi.FindControl("txtCategoryName"),
TextBox).Text
56: cmd = New
OleDbCommand(strSQL, con)
57: With
cmd.Parameters
58:
.Add("@CategoryName",strCategoryName)
59:
.Add("@CategoryID",intCategoryID)
60: End With
61: con.Open()
62:
cmd.ExecuteNonQuery()
63:
con.Close()
64: End If
65: Next
66: marrCategoryList.Clear()
67: marrCategoryList.TrimToSize()
68: LoadData()
69: BindDataGrid()
70: End Sub