ASP.NETでは、データを一覧表示するのに、もはやTABLEタグやループ処理をチマチマ記述する必要はない。値の編集も一覧上で可能だ。
前回で解説したデータ連結はすべて、ページがコンテナとなるコントロールを対象としてきたが、ASP.NETではコンテナとして機能するコントロールが3つ用意されている(コンテナは、コントロールなどの複数のオブジェクトを格納するオブジェクト)。これらはasp:DataList、asp:DataGrid、asp:Repeaterコントロールである。この3種類のサーバ・コントロールは、特に「データリスト・コントロール」と呼ばれている。今回はこのうち、asp:DataListコントロールについて詳しく見ていく。
オブジェクトの集合に対する反復処理をサポートするIEnumerableインターフェイスを実装したデータソースを受け取り、前回解説した反復値データ連結を行うという点では、データリスト・コントロールと、第8回で解説したリスト系コントロールに違いはない。しかしデータリスト・コントロールでは、その子要素にデータ連結式を記述してデータソースを参照できるため、データ連結の結果を自由にカスタマイズできるところが大きく異なっている。
それでは、データリスト・コントロールの扱い方をasp:DataListコントロールを使って解説していくことにしよう。まずリスト10.1を見て欲しい。asp:DataListコントロールのデータソースに配列を設定し、データ連結しているところまでは、前回までの解説と相違ない。注目して欲しいのは、asp:DataListコントロールの子要素として記述されているデータ連結式(<%# Container.DataItem %>)である。
<%@ PAGE LANGUAGE="C#" %>
<%@ Import Namespace="System.Data" %>
<html>
<head>
<script runat="server">
void Page_Load(object sender, EventArgs e) {
  if (!IsPostBack) {
    string[] source = { "item1", "item2", "item3" };
    datalist1.DataSource = source;
    datalist1.DataBind();
  }
}
</script>
</head>
<body>
  <asp:DataList id="datalist1" runat="server">
    <ItemTemplate>
      <%# Container.DataItem %>
    </ItemTemplate>
  </asp:DataList>
</body>
</html>
このASP.NETページを実行すると、図10.1に示すように、データソースの要素であるitem1〜item3がテーブルとして1列に表示される。突然登場したContainerオブジェクトやDataItemプロパティが何者で、なぜこのデータ連結式でデータソースが一覧されるのか。その仕組みを解説する前に、asp:DataListコントロールの機能について触れておこう。
asp:DataListコントロールは、データソースの要素を表形式に出力する機能を持ったサーバ・コントロールである。その出力形式は次の表10.1に示す属性(プロパティとしてもアクセス可能)を指定することで、さまざまにカスタマイズが可能だ。各属性の具体的な効果については、リスト10.2に示すサンプル・プログラムで確認して欲しい。
| 属性 | 機能 | 
|---|---|
| CellPadding | セル内部とグリッド線(ボーダーライン)との間隔(ピクセル単位) | 
| CellSpacing | セル外枠とグリッド線(ボーダーライン)との間隔(ピクセル単位) | 
| GridLines | グリッド線のスタイル | 
| RepeatColumns | 表のカラム数 | 
| RepeatDirection | 要素の整列方向 | 
| RepeatLayout | 要素の整列方法 | 
| 表10.1 asp:DataListコントロールの属性 | |
<%@ PAGE LANGUAGE="C#" %>
<%@ Import Namespace="System.Data" %>
<html>
<head>
<script runat="server">
void Page_Load(object sender, EventArgs e) {
  if (!IsPostBack) {
    foreach (string name in Enum.GetNames(typeof(GridLines))) {
      lines.Items.Add(new ListItem(name));
    }
    foreach (string name in Enum.GetNames(typeof(RepeatDirection))) {
      direction.Items.Add(new ListItem(name));
    }
    foreach (string name in Enum.GetNames(typeof(RepeatLayout))) {
      layout.Items.Add(new ListItem(name));
    }
    string[] source = {
      "item1", "item2", "item3", "item4", "item5", "item6",
      "item7", "item8", "item9", "item10", "item11", "item12" };
    datalist1.DataSource = source;
    datalist1.DataBind();
  } else {
    try {
      datalist1.CellPadding = Int32.Parse(padding.Text);
      datalist1.CellSpacing = Int32.Parse(spacing.Text);
      datalist1.RepeatColumns = Int32.Parse(columns.Text);
    }
    catch (Exception ex) {
      padding.Text = "0";
      spacing.Text = "0";
      columns.Text = "1";
    }
    GridLines gl = (GridLines) Enum.Parse(
      typeof(GridLines), lines.SelectedItem.Text);
    datalist1.GridLines = gl;
    RepeatDirection rd = (RepeatDirection) Enum.Parse(
      typeof(RepeatDirection), direction.SelectedItem.Text);
    datalist1.RepeatDirection = rd;
    RepeatLayout rl = (RepeatLayout) Enum.Parse(
      typeof(RepeatLayout), layout.SelectedItem.Text);
    datalist1.RepeatLayout = rl;
  }
}
</script>
</head>
<body>
<form runat="server">
  CellPadding : <asp:TextBox id="padding" Text="0" runat="server" />
  CellSpacing : <asp:TextBox id="spacing" Text="0" runat="server" />
  GridLines : <asp:DropDownList id="lines" runat="server" />
  <br>
  RepeatColumns : <asp:TextBox id="columns" Text="1" runat="server" />
  RepeatDirection : <asp:DropDownList id="direction" runat="server" />
  RepeatLayout : <asp:DropDownList id="layout" runat="server" />
  <br>
  <asp:Button Text="Submit" runat="server" />
  <asp:DataList id="datalist1" runat="server">
    <ItemTemplate>
      <%# Container.DataItem %>
    </ItemTemplate>
  </asp:DataList>
</form>
</body>
</html>
さて、話題をこのデータ連結式に戻そう。
<%# Container.DataItem %>
ここで浮かぶ疑問は、Containerオブジェクトが何者であるか、だろう。結論からいえば、Containerはデータソースの要素を格納するコンテナ・オブジェクトである。そのデータ型はデータリスト・コントロールの種類によって決まり、asp:DataListコントロールではDataListItemオブジェクトがコンテナとして利用される(表10.2)。
| コントロール | Containerのデータ型 | 
|---|---|
| asp:DataList | DataListItem | 
| asp:DataGrid | DataGridItem | 
| asp:Repeater | RepeaterItem | 
| 表10.2 Containerオブジェクトのデータ型 | |
それでは、Containerオブジェクトはどこからきたのか? このオブジェクトは、リスト10.2のどこでも定義されていないし、Pageクラスのメンバでもない。これはもう、データリスト・コントロールのデータ連結式でのみ参照可能な、暗黙的に定義された特殊なオブジェクトであるとしかいいようがない。データリスト・コントロールでは、Pageクラスと、ページ内のクラスのフィールドやメソッドだけでなく、このContainerオブジェクトを通してデータソースへアクセスできる。データソースを参照して、反復値データ連結を行うという動作はリスト系コントロールでも見られたが、データリスト・コントロールでは、データ連結式を記述して、出力形式を細かくカスタマイズできるのである。
Containerが参照するDataListItemオブジェクトには、次の表10.3に示す3種類のプロパティが定義されている。ここで最も重要なプロパティが、データ連結された要素を参照するDataItemプロパティである。
| プロパティ | 値 | 
|---|---|
| object DataItem | データ連結された要素 | 
| int ItemIndex | 要素のインデックス | 
| ListItemType ItemType | 要素の種類 | 
| 表10.3 DataListItemクラスのプロパティ | |
リスト系コントロールの解説で、反復値データ連結によって取り出される各要素のデータ型はデータソースによって異なると述べた。これはデータリスト・コントロールでも同じである。従って、データソースがstringの配列ならばContainer.DataItemはstringオブジェクトを参照し、データソースがHashtableならばDictionaryEntryオブジェクトを参照し、データソースがDataViewならばDataRowViewオブジェクトを参照する(表10.4)。
| データソース | 要素 | 
|---|---|
| string[] | string | 
| Hashtable | DictionaryEntry | 
| DataView | DataRowView | 
| 表10.4 データソースと要素のデータ型の対応 | |
上記のリスト10.1では、データソースにstringの配列を設定していたため、Container.DataItemには文字列“Item1”〜“Item3”が順にContainer.DataItemに代入され、反復値データ連結が行われた結果、図10.1に見たように“Item1”〜“Item3”が一覧表示される表が出力されたのである。
Copyright© Digital Advantage Corp. All Rights Reserved.