asp.netのrepeaterで表示・編集・登録処理を行う その1
ASP.NET
のWEBサーバコントロールのRepeater
コントロールを使用し、データの表示・編集・登録処理の流れの実装例を紹介します。
具体的には、DBに登録されているデータをRepeater
コントロールを使い、エクセルのような表形式で表示し、ユーザがデータを編集して、更新するという流れです。
下記のようにテキストボックス、ラジオボタン、チェックボックス、コンボボックスでそれぞれのパターンで編集できるようにします。
選手名 | 国籍 | 怪我 | キャプテン |
---|---|---|---|
Repeaterコントロールの基本
まず初めに、Repeater
の基本的な使い方について説明します。
Repeater
はGridView
と同じように、データテーブルをバインドして、データテーブルの件数分、html
を生成してくれるコントロールです。
データテーブルだけでなく、配列などもバインドすることができますが、今回は表形式で出力するため、データテーブルをバインドします。
Repeaterコントロールの中にhtmlサーバコントロールを定義
まずはユーザがデータを編集できるようにテキストボックスを定義します。
webサーバコントロールでも問題ありませんが、レスポンスをわかりやすくするためにhtmlサーバコントロールを使用します。
htmlサーバコントロールとwebサーバコントロールの違いについてはasp.netのhtmlサーバコントロールの基本とasp.netのwebサーバコントロールの基本をご覧ください。
サーバ処理でコントロールにアクセスするためにrunat="server"
をつけるのを忘れないようにします。
HeaderTemplate
はバインドした際に1度だけ実行されます。ItemTemplate
はバインドしたデータの件数分実行されます。FooterTemplate
は最後に1度だけ実行されます。
今回はデータ件数分の行(table
のtr
要素)を出力するため、tr
をItemTemplate
の中に定義します。
国籍コンボボックスの中身はあらかめhtml
に定義しておいてもいいのですが、コンボボックスの中身もDBから読み込んで動的に設定することが多いので、この時点ではセットしません。
<table>
<thead>
<tr>
<td>選手名</td>
<td>国籍</td>
<td>怪我</td>
<td>キャプテン</td>
</tr>
</thead>
<tbody>
<asp:Repeater ID="repeater1" runat="server">
<ItemTemplate>
<tr>
<td><input type="text" id="txtName" runat="server" /></td>
<td><select id="selCountry" runat="server"></select></td>
<td><input type="checkbox" id="chkInjure" runat="server" /></td>
<td><input type="radio" id="rdoCap" runat="server" /></td>
</tr>
</ItemTemplate>
</asp:Repeater>
</tbody>
</table>
サーバ処理でレスポンスするhtmlを作成
まずはRepeater
にバインドするデータテーブルをDBなどから取得します。今回はバインドするデータテーブルの中身は下記のようにします。
NAME | COUNTRY | INJURE | CAPTAIN |
---|---|---|---|
選手名1 | jp | 0 | 1 |
選手名2 | us | 1 | 0 |
選手名3 | jp | 0 | 0 |
このデータをRepeater
コントロールにバインドします。
repeater1.DataSource = dt
repeater1.DataBind()
しかし、バインドしただけではテキストボックスに値をセットしたり、チェックボックスにチェックをしたりすることはできません。
また、Repeater
の中に定義したコントロールはrunat="server"
がついていても、そのままアクセスできません。例えばtxtName.value="test"
としても、ビルドエラーになってしまいます(どの行のtxtNameかわからないので)。
取得するには対象の1行に対してFindControl
を使用して取得します。
バインドしたあとにRepeater
コントロールにアクセスして、コントロールに値をセットしてもいいのですが、今回はRepeater
にはバインドしたら1行ごとに発生するItemDataBound
というイベントが用意されていますので、そのイベントの中でテキストボックスなどのコントロールに値をセットします。
Sub repeater1_ItemDataBound(Byval Sender As Object, _
Byval e As RepeaterItemEventArgs) Handles repeater1.ItemDataBound
'HeaderTemplateとFooterTemplateのときは処理を飛ばします
If e.Item.ItemType = ListItemType.Item Or _
e.Item.ItemType = ListItemType.AlternatingItem Then
'現在のバインドしている行を取得します DataTableをバインドした場合はDataRowViewになります
Dim row As DataRowView = CType(e.Item.DataItem, DataRowView)
'テキストボックスのコントロールを取得 e.Itemで現在の行のhtml(aspx)を取得できます
Dim textControl As HtmlInputTextBox = CType(e.Item.FindControl("txtName"), HtmlInputTextBox)
'コントロールにバインドしたデータの値をセットします
textControl.value = row("NAME").ToString
'コンボボックスのコントロールを取得
Dim selectControl As HtmlSelect = CType(e.Item.FindControl("selCountry"), HtmlSelect)
'コンボボックスの値をセットします
selectControl.Add(new ListItem("日本", "jp"));
selectControl.Add(new ListItem("アメリカ", "us"));
'コントロールにバインドしたデータの値をセットします
selectControl.value = row("COUNTRY").ToString
'チェックボックスのコントロールを取得
Dim checkboxControl As HtmlInputCheckBox = CType(e.Item.FindControl("chkInjure"), HtmlInputCheckBox)
'コントロールにバインドしたデータの値をセットします
If row("INJURE").ToString = "1" Then
checkboxControl.checked = True
Else
checkboxControl.checked = False
End If
'ラジオボタンのコントロールを取得
Dim radioControl As HtmlInputRadioButton = CType(e.Item.FindControl("rdoCap"), HtmlInputRadioButton)
'コントロールにバインドしたデータの値をセットします
If row("CAPTAIN").ToString = "1" Then
radioControl.checked = True
Else
radioControl.checked = False
End If
End If
End Sub
埋め込みで値を出力する方法
バインドした変数などをclassic asp
やphp
のように埋め込みで出力することもできます。
ASP.NET
でも普通の変数なら<%= 変数名 %>
で埋め込みで出力することができますが、Repeater
やGridView
のようにバインドしたテーブルの値を出力したい場合は下記のような方法になります。
<%# DataBinder.Eval(Container.DataItem, "NAME") %>
なので、例えばtxtName
の値を埋め込みで出力する場合は下記のようになります。
<input type="text" id="txtName" runat="server" value='<%# DataBinder.Eval(Container.DataItem, "NAME") %>' />
これでクライアント側にデータを表示することが出来ました。しかし、Repeater
やGridView
などで動的に作成したhtml
のコントロールはIDやNAME属性が連番に置き換わってしまいます。
例えば1行目のtxtName
だと、repeater1_ctr0_txtName
などになってしまいます。
置き換わる文字列は一見規則性があるように見えますが、環境によってパターンが変わったりします。
これがクライアント側での処理を少し複雑にしてしまいます。