第10回 Webフォームにおけるデータ連結 Part2 DataListコントロール:連載 プログラミングASP.NET ―ASP.NETによるWebアプリケーション実践開発講座― (4/4 ページ)
ASP.NETでは、データを一覧表示するのに、もはやTABLEタグやループ処理をチマチマ記述する必要はない。値の編集も一覧上で可能だ。
asp:DataListコントロールのイベント
それでは、どのようにして[編集]ボタンや[選択]ボタンをクリックするとセルの状態が変化したのか、その仕組みを見ていくことにしよう。
■asp:DataListコントロールのイベント(選択)
まず[選択]ボタンだが、このボタンはItemTemplateなどで次のように定義されていた。
<asp:LinkButton Text="選択" CommandName="choice" runat="server" />
これは「ボタン系コントロール」で解説したように、CommandName属性が指定されたコマンド・ボタンである。ただし、asp:DataListコントロールのテンプレートで使われるコマンド・ボタンは、通常のコマンド・ボタンと少し違う。まずイベント・ハンドラの設定方法だが、各コマンド・ボタンにOnClick属性を設定するのではなく、asp:DataListのOnItemCommand属性を使って以下のように設定する。ここでは、「datalist1_Choice」の名前でイベント・ハンドラとなるメソッドを指定している。
<asp:DataList id="datalist1"
OnItemCommand="datalist1_Choice"
runat="server">
これによって、asp:DataListコントロールに含まれるすべてのコマンド・ボタンをクリックすると、datalist1_Choiceメソッドが呼び出されるようになる。このOnItemCommand属性に対応するイベント・ハンドラは、次のシグネチャで定義する。
void datalist1_Choice(object sender, DataListCommandEventArgs e) {
if (e.CommandName == "choice") {
datalist1.SelectedIndex = e.Item.ItemIndex;
datalist1.DataSource = CreateDataSource();
datalist1.DataBind();
}
}
イベント・パラメータを格納するオブジェクトの型がCommandEventArgsではなく、DataListCommandEventArgsであることに注意して欲しい。DataListCommandEventArgsには、CommandEventArgsにないItemプロパティが追加されている。Itemプロパティはコマンド・ボタンをクリックした要素に対応するDataListItemオブジェクトを参照しており、次の表10.6に示すメンバへアクセスして、各種情報を取得することができる。なお、Itemプロパティが参照するオブジェクトは、データ連結式で参照できるContainerが参照するオブジェクトと同じものである。
メンバ | 説明 |
---|---|
int ItemIndex | 0から始まるデータソース要素のインデックス |
Control FindControl(string id) | id属性を指定してコントロールを検索する |
表10.6 DataListItemクラスの主要メンバ |
asp:DataListには1つしかOnItemCommandイベント・ハンドラを指定することができないため、このイベント・ハンドラでは、コマンド名(ここではリンク・ボタンのCommandName属性に指定した“choice”)が格納されているDataListCommandEventArgs.CommandNameプロパティを参照して、処理を振り分ける必要がある。
CommandNameの値が“choice”であることを確認したら、次にDataList.SelectedIndexプロパティにItemIndexプロパティの値を設定する。ItenIndexにはボタンをクリックした要素のインデックスが格納されているため、これでその要素が選択状態になる。そうしたら、CreateDataSourceメソッドを呼び出して再度データソースを作成し、DataBindメソッドでデータ連結を行う。これで、SelectedIndexプロパティで指定した要素がSelectedItemTemplateにデータ連結されたページが生成される。
asp:DataListコントロールにコマンド・ボタンを実装する手順をまとめると次のようになる。
- CommandName属性を指定したコマンド・ボタンを用意する
- asp:DataListのOnItemCommand属性にイベント・ハンドラを指定する
- 以下のシグネチャでイベント・ハンドラを定義する
void <メソッド名>(object sender, DataListCommandEventArgs e)
■asp:DataListコントロールのイベント(編集)
asp:DataListコントロールのコマンド・ボタンは、すべてOnItemCommand属性に指定したメソッドでハンドリングされると述べたが、次の表10.7に示すコマンド名をCommandName属性に指定した場合に限っては、特別なイベント・ハンドラ設定属性が用意され、個別にイベント・ハンドラを設定することができる。もっとも、イベント・ハンドラに渡されるイベント・パラメータは、selectコマンドを除けばOnItemCommandと同じDataListCommandEventArgsオブジェクトであり、単にイベント・ハンドラを分けられる以上の意味はない。従って、イベント・ハンドラを定義するまでの作業は、コマンド名やイベント・ハンドラ設定属性が異なるだけで、OnItemCommandによる汎用イベント・ハンドラとまったく変わらない。
コマンド | イベント・ハンドラ設定属性 | シグネチャ |
---|---|---|
Edit | OnEditCommand属性 | void <メソッド名>(object sender, DataListCommandEventArgs e) |
update | OnUpdateCommand属性 | 同上 |
cancel | OnCancelCommand属性 | 同上 |
delete | OnDeleteCommand属性 | 同上 |
select | OnSelectedIndexChanged属性 | void <メソッド名>(object sender, EventArgs e) |
表10.7 特殊なコマンド・ボタンとイベント・ハンドラ設定属性 |
例えば、edit、update、cancelコマンド・ボタンを利用するには、リスト10.4に示したように、以下のようにイベント・ハンドラ設定属性、コマンド・ボタンのコマンド名、それにイベント・ハンドラを記述すればよい。
<asp:DataList id="datalist1"
OnEditCommand="datalist1_Edit" editコマンド・ボタンに対応
OnUpdateCommand="datalist1_Update" updateコマンド・ボタンに対応
OnCancelCommand="datalist1_Cancel" cancelコマンド・ボタンに対応
runat="server">
<ItemTemplate>
<asp:LinkButton Text="編集" CommandName="edit" runat="server" />
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton Text="更新" CommandName="update" runat="server" />
<asp:LinkButton Text="キャンセル" CommandName="cancel" runat="server" />
</EditItemTemplate>
</asp:DataList>
<script runat="server">
void datalist1_Edit(object sender, DataListCommandEventArgs e) { … }
void datalist1_Update(object sender, DataListCommandEventArgs e) { … }
void datalist1_Cancel(object sender, DataListCommandEventArgs e) { … }
</script>
それでは次に、各コマンド(edit、update、cancel)の実装方法について解説しよう。まずeditコマンドだが、ここでの典型的な処理の目的は、[編集]ボタンをクリックした要素を編集対象として設定することにある。そのためには、以下に示すようにDataList.EditItemIndexプロパティに、e.Item.ItemIndex(ボタンをクリックした要素のインデックス)を代入すればよい。こうして再度データ連結を行えば、指定した要素がEditItemTemplateによってデータ連結される。
void datalist1_Edit(object sender, DataListCommandEventArgs e) {
datalist1.EditItemIndex = e.Item.ItemIndex;
datalist1.DataSource = CreateDataSource();
datalist1.DataBind();
}
編集対象に設定した要素を解除するには、同じDataList.EditItemIndexに-1を設定すればよい。こうして再度データ連結を行えば、すべての要素がItemTemplateによってデータ連結される。
void datalist1_Cancel(object sender, DataListCommandEventArgs e) {
datalist1.EditItemIndex = -1;
datalist1.DataSource = CreateDataSource();
datalist1.DataBind();
}
最後に示すupdateコマンドのハンドラでは、恐らく最も複雑な処理が行われるはずだ。リスト10.4では特別な更新処理は行っていないが、実際には、以下に示すようにユーザーによって入力された情報を取得して、必要に応じてデータソースの更新を行うことになる。
void datalist1_Update(object sender, DataListCommandEventArgs e) {
int fileid = (int) datalist1.DataKeys[e.Item.ItemIndex];
TextBox textbox = (TextBox) e.Item.FindControl("filename");
/* 取得した情報を用いて、ここでデータソースの更新を行う */
datalist1.EditItemIndex = -1;
datalist1.DataSource = CreateDataSource();
datalist1.DataBind();
}
まずここでは、EditItemTemplateで定義したテキスト・ボックスなどのサーバ・コントロールへの参照を入手して、そこからユーザーが入力した値を取得しなければならないはずだ。このために利用できるメソッドがControl.FindControlメソッドである(ControlクラスはDataListItemクラスのベース・クラス)。e.Itemプロパティからこのメソッドを呼び出せば、[更新]ボタンをクリックした要素に表示されているコントロールを名前(ID属性に指定した値)で検索し、取得することができる。なお、FindControlメソッドはControlオブジェクトを返すので、必要に応じてキャストしてから各プロパティへアクセスする必要がある。
また、更新処理を行うには、ユーザーが入力した情報だけでなく、データソースに含まれているが、データ連結には使われていない値が必要になる場合がある。例えば、データベースから取得したアイテムの情報を更新したいとしよう。この場合、各アイテムを識別するためにID値が必要になる。しかし、このID値をデータベースから取得してデータソースに格納しても、ページ(画面)に出力する必要はないため、データ連結は行わないはずだ。このようにデータソースにあっても、データ連結されていない値へイベント・ハンドラから参照するには、データキーの仕組みが利用できる。
データソースの特定のフィールドをデータキーとして指定するには、asp:DataListのDataKeyField属性にフィールド名を指定する。
<asp:DataList id="datalist1"
DataKeyField="fileid"
runat="server">
するとイベント・ハンドラからDataList.DataKeysコレクションプロパティを通して、指定したフィールドの値にアクセスできる。このときe.Item.ItemIndexをインデックスに指定すれば、[更新]ボタンをクリックした要素のデータキー・フィールドにアクセスできる。なお、データキーの値はobject型として返されるので、必要に応じてキャストする必要がある。
int fileid = (int) datalist1.DataKeys[e.Item.ItemIndex];
こうして必要な情報を取得したら、データベースやファイルなど、データストアの情報を更新すればよい。
■[選択]ボタン
以上でリスト10.4の解説を終えるが、最後にselectコマンドについて解説しておこう。リスト10.4では、コマンド名に“choice”が指定されたコマンド・ボタンを使って、[選択]ボタンを実装していたが、実はasp:DataListコントロールには、[編集]ボタンのように、[選択]ボタンを実装するための特別なコマンド名selectが用意されている。このコマンド・ボタンを利用すれば、汎用のOnItemCommandではなく、専用のイベント・ハンドラをOnSelectedIndexChangedで指定できる。
<asp:DataList id="datalist1"
OnSelectedIndexChanged="datalist1_Select"
runat="server">
void datalist_Select(object sender, EventArgs e) {
/* datalist1.SelectedIndexの設定は不要 */
datalist1.DataSource = CreateDataSource();
datalist1.DataBind();
}
また、コマンド名selectには、ちょっとした特別な機能も備わっている。それは、DataList.SelectedIndexプロパティが自動的に設定され、クリックした[選択]ボタンを含む要素が自動的に選択されるのである。もっとも、データソースの指定やデータ連結の実行は明示的に行う必要があるため、省略できるコードはたった1行にすぎず、上記のようにイベント・ハンドラを実装する必要はある。
今回はDataListコントロールとそのデータ連結について述べた。テンプレートさえ記述すれば、ループ処理なしにデータをテーブル形式で表示でき、テーブル内で編集まで可能な非常に強力なコントロールである。次回はデータを「グリッド形式」で表示し、データの並べ替えやページング表示も可能になっている、より強力な「DataGridコントロール」について解説する予定だ。
Copyright© Digital Advantage Corp. All Rights Reserved.