第10回 Webフォームにおけるデータ連結 Part2 DataListコントロール:連載 プログラミングASP.NET ―ASP.NETによるWebアプリケーション実践開発講座― (2/4 ページ)
ASP.NETでは、データを一覧表示するのに、もはやTABLEタグやループ処理をチマチマ記述する必要はない。値の編集も一覧上で可能だ。
DataBinder.Evalメソッド
リスト系コントロールに反復値データ連結を行うとき、オブジェクトを文字列に変換するという基本ルール以外の方法でデータ連結を行うには、DataTextFieldとDataValueFieldを設定すると前回で解説した。この種の操作はデータリスト・コントロールでも必要だが、asp:DataListコントロールにDataTextField属性やDataValueField属性は用意されていない。データリスト・コントロールでは、データ連結式を使ってより柔軟に要素へアクセスできるため、実は非常に限定的なデータ連結式の一種でしかないDataTextFieldとDataValueFieldによる要素へのアクセスは不要なのである。
例えば、asp:DataListコントロールのデータソースにHashtableオブジェクトを設定したとしよう。この場合、次のデータ連結式でKeyプロパティとValueプロパティを参照することができる(要素のデータ型はDictionaryEntry)。
<%# ((DictionaryEntry)Container.DataItem).Key %>
<%# ((DictionaryEntry)Container.DataItem).Value %>
また同様に、データソースにDataViewオブジェクトを設定した場合には、次のようにして各フィールドを参照できる。
<%# ((DataRowView)Container.DataItem)["text"] %>
<%# ((DataRowView)Container.DataItem)["value"] %>
いずれもContainer.DataItemを要素のデータ型へとキャストしているため少し複雑に見えるが、これはContainer.DataItemがobject型プロパティとして定義されているためである。もし「<%# Container.DataItem.Key %>」のようなデータ連結式を記述すれば、「object型のメンバにKeyは定義されていない」とエラー・メッセージが表示されてしまうだけだ。しかし、常にキャストを行わなければならないのでは、データ連結式が複雑になってしまう上、データソース要素のデータ型を常に把握していなければならなくなってしまう。そこで、この繁雑さを解消するために用意されているのがDataBinder.Evalメソッドである。
このDataBinderクラスの静的メソッドを利用すると、上記のデータ連結式を以下のように書き換えることができる。ご覧のとおりキャストを取り除き、ごくシンプルな書式でのデータ連結が可能になる。
<%# DataBinder.Eval(Container.DataItem, "Key") %>
<%# DataBinder.Eval(Container.DataItem, "Value") %>
<%# DataBinder.Eval(Container.DataItem, "text") %>
<%# DataBinder.Eval(Container.DataItem, "value") %>
このようにDataBinder.Evalメソッドを利用すれば、リフレクションを利用して第1引数のデータ型を調べ、適切な方法で第2引数に指定されたプロパティあるいはインデクサへの参照を解決することができる。なお、Evalメソッドの第2引数には、プロパティ名やインデクサだけでなく、以下の形式の<メンバ>部分に記述可能なあらゆる式を指定できる。
<%# ((<要素のデータ型>)Container.DataItem).<メンバ> %>
ただし、DataBinder.Evalメソッドにはデメリットもある。Evalメソッドはリフレクションによる自動型変換を実行時に行うため、多少の処理時間を要するのである。もし要素のデータ型が明確になっていて、なおかつキャストをいとわないのであれば、DataBinder.Evalメソッドを使わずに明示的にキャストを行った方が処理効率は向上する。次のリスト10.3では、いくつかの種類のオブジェクトに対して、それぞれの方法でデータ連結を記述した例を示した。
<%@ PAGE LANGUAGE="C#" %>
<%@ Import Namespace="System.Data" %>
<html>
<head>
<script runat="server">
void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
string[] array = { "item1", "item2", "item3" };
datalist1.DataSource = array;
ArrayList arraylist = new ArrayList();
arraylist.Add("item1");
arraylist.Add("item2");
arraylist.Add("item3");
datalist2.DataSource = arraylist;
Hashtable ht = new Hashtable();
ht.Add("item1", "0");
ht.Add("item2", "1");
ht.Add("item3", "2");
datalist3.DataSource = ht;
datalist4.DataSource = ht;
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("text", typeof(String)));
dt.Columns.Add(new DataColumn("value", typeof(Int32)));
DataRow dr;
for (int i = 0; i < 3; i++) {
dr = dt.NewRow();
dr[0] = "item" + (i + 1);
dr[1] = i;
dt.Rows.Add(dr);
}
datalist5.DataSource = new DataView(dt);
datalist6.DataSource = new DataView(dt);
DataBind();
} else {
}
}
</script>
</head>
<body>
<form runat="server">
<table border="1">
<tr><td>Array</td><td>ArrayList</td>
<td>Hashtable(DataBinder有)</td><td>Hashtable(DataBinder無)</td>
<td>DataView(DataBinder有)</td><td>DataView(DataBinder無)</td>
</tr>
<tr>
<td>
<asp:DataList id="datalist1" runat="server">
<ItemTemplate>
<%# Container.DataItem %>
</ItemTemplate>
</asp:DataList>
</td><td>
<asp:DataList id="datalist2" runat="server">
<ItemTemplate>
<%# Container.DataItem %>
</ItemTemplate>
</asp:DataList>
</td><td>
<asp:DataList id="datalist3" runat="server">
<ItemTemplate>
<%# DataBinder.Eval(Container.DataItem, "Key") %>
<%# DataBinder.Eval(Container.DataItem, "Value") %>
</ItemTemplate>
</asp:DataList>
</td><td>
<asp:DataList id="datalist4" runat="server">
<ItemTemplate>
<%# ((DictionaryEntry)Container.DataItem).Key %>
<%# DataBinder.Eval(Container.DataItem, "Value") %>
</ItemTemplate>
</asp:DataList>
</td><td>
<asp:DataList id="datalist5" runat="server">
<ItemTemplate>
<%# DataBinder.Eval(Container.DataItem, "text") %>
<%# DataBinder.Eval(Container.DataItem, "value") %>
</ItemTemplate>
</asp:DataList>
</td><td>
<asp:DataList id="datalist6" runat="server">
<ItemTemplate>
<%# ((DataRowView)Container.DataItem)["text"] %>
<%# DataBinder.Eval(Container.DataItem, "value") %>
</ItemTemplate>
</asp:DataList>
</td></table>
</form>
</body>
</html>
sample08.aspxのダウンロード(sample08.zip)
Copyright© Digital Advantage Corp. All Rights Reserved.