検索
連載

第10回 Webフォームにおけるデータ連結       Part2 DataListコントロール連載 プログラミングASP.NET ―ASP.NETによるWebアプリケーション実践開発講座― (3/4 ページ)

ASP.NETでは、データを一覧表示するのに、もはやTABLEタグやループ処理をチマチマ記述する必要はない。値の編集も一覧上で可能だ。

Share
Tweet
LINE
Hatena

asp:DataListコントロールのテンプレート

 前回の内容と合わせ、ここまででデータ連結に関する基本的な解説は終わりだ。ここからはasp:DataListコントロールの機能について解説を進めていくことにする。

 すでに何度かリストで示したように、asp:DataListコントロールは次の書式で指定された<セルに表示する内容>部分を、反復値データ連結を使ってテーブルの各セルに展開する機能を備えている。<セルに表示する内容>には、データ連結式以外にも、サーバ・コントロールやHTMLエレメント、それにリテラル文字列を記述することが可能だ。ただし、ここに記述した内容はテーブルのTDエレメント、あるいはSPANエレメントで囲まれる形で出力されることには注意が必要である。<セルに表示する内容>にエレメントを記述するときは、必ず開始タグと終了タグを対にして、完結するように指定しなければならない。

  <asp:DataList runat="server">
    <ItemTemplate>
      <セルに表示する内容>
    </ItemTemplate>
  </asp:DataList>

■テンプレートの種類

 ところで、ここまでasp:DataListコントロールの要素としてItemTemplateだけを利用してきたが、そのほかにも次の表10.5に示すテンプレートが用意されている。これらのテンプレートをItemTemplateと併記することで、asp:DataListコントロールをカスタマイズすることができる。

   
ItemTemplate データソースの各要素が連結される
AlternatingTemplate このテンプレートが定義されていると、ItemTemplateと交互に連結されるようになる(1つの要素はItemTemplateとAlternatingTemplateの一方にのみ連結される)
EditItemTemplate 編集用テンプレート。EditItemIndexプロパティで指定された要素が連結される
SelectedItemTemplate 選択要素用テンプレート。SelectedIndexプロパティで指定された要素が連結される
SeparatorTemplate 各要素の合間に出力される(データソースへのデータ連結なし)
HeaderTemplate 上端に出力される(データソースへのデータ連結なし)
FooterTemplate 下端に出力される(データソースへのデータ連結なし)
表10.5 asp:DataListコントロールのテンプレート

 データソースが連結されると、各要素はItemTemplate、AlternatingTemplate、EditItemTemplate、SelectedItemTemplateの4種類のテンプレートのいずれか1つによってデータ連結され、ページとして出力される。1つの要素が複数のテンプレートによってデータ連結されることはない。また、同じテンプレートを2回以上定義すると後で定義した方だけが有効になり、先に定義された方は無視される。

 ItemTemplateテンプレートしか定義されていなかったときは、すべての要素がItemTemplateによってデータ連結されるが、それ以外の3つのテンプレートが定義されているときは、簡単なルールでデータ連結に使われるテンプレートが選択される。まず、ItemTemplateに加えて、AlternatingTemplateが定義されているときには、ItemTemplateとAlternatingTemplateが交互に参照されてデータ連結が行われるようになる。繰り返しになるが、1つの要素が複数のテンプレートによって連結されることはないので、1つの要素はItemTemplateとAlternatingTemplateの一方でのみ連結される。このテンプレートは主に、交互にセルの背景色を変えるなど、スタイルの設定用途に使われるものだ。この場合は、ItemTemplateと同じ<セルに表示する内容>をAlternatingTemplateにも指定して、AlternatingItemStyleとItemStyleを設定することになるが、Sytleについての解説はここでは割愛する。

 残りの2つのテンプレートは、初期状態で使われることはないが、次のプロパティで指定された要素に対して、ItemTemplateやAlternatingTemplateよりも優先して使われる。EditItemTemplateはDataListクラスのEditItemIndexプロパティで指定された要素に対するデータ連結で使われ、SelectedItemTemplateは同じくSelectedIndexプロパティで指定された要素に対するデータ連結で使われる。これについて詳しくは後述する。

 以上4つのテンプレートはデータソースに連結可能だが、残りのSeparatorTemplate、HeaderTemplate、FooterTemplateは連結できない(Container.DataItemオブジェクトを参照できない)。ただし、Pageクラスや、ページ内のクラスのプロパティやメソッドは参照できるので、単一値データ連結だけは利用可能だ。

■テンプレートの利用法

 各テンプレートを利用したサンプル・プログラム(リスト10.4)を見ながら、テンプレートの具体的な利用方法について解説していこう。

<%@ PAGE LANGUAGE="C#" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.IO" %>
<html>
<head>
<script runat="server">
void Page_Load(object sender, EventArgs e) {
  if (!IsPostBack) {
    datalist1.DataSource = CreateDataSource();
    datalist1.DataBind();
  }
}

ICollection CreateDataSource() {
  DirectoryInfo di = new DirectoryInfo(Server.MapPath("."));
  FileInfo[] fi = di.GetFiles();

  DataTable dt = new DataTable();
  DataRow dr;

  dt.Columns.Add(new DataColumn("fileid", typeof(int)));
  dt.Columns.Add(new DataColumn("filename", typeof(String)));
  dt.Columns.Add(new DataColumn("filesize", typeof(long)));
  dt.Columns.Add(new DataColumn("date", typeof(DateTime)));

  for (int i = 0; i < fi.Length; i++) {
    dr = dt.NewRow();
    dr[0] = i;
    dr[1] = fi[i].Name;
    dr[2] = fi[i].Length;
    dr[3] = fi[i].LastWriteTime;
    dt.Rows.Add(dr);
  }

  DataView dv = new DataView(dt);

  return dv;
}

void datalist1_Edit(object sender, DataListCommandEventArgs e) {
  datalist1.EditItemIndex = e.Item.ItemIndex;
  datalist1.DataSource = CreateDataSource();
  datalist1.DataBind();
}

void datalist1_Update(object sender, DataListCommandEventArgs e) {
  int fileid = (int) datalist1.DataKeys[e.Item.ItemIndex];
  TextBox textbox = (TextBox) e.Item.FindControl("filename");

  Message.Text = fileid.ToString() + " : " + textbox.Text;

  datalist1.EditItemIndex = -1;
  datalist1.DataSource = CreateDataSource();
  datalist1.DataBind();
}

void datalist1_Cancel(object sender, DataListCommandEventArgs e) {
  datalist1.EditItemIndex = -1;
  datalist1.DataSource = CreateDataSource();
  datalist1.DataBind();
}

void datalist1_Choice(object sender, DataListCommandEventArgs e) {
  if (e.CommandName == "choice") {
    datalist1.SelectedIndex = e.Item.ItemIndex;
    datalist1.DataSource = CreateDataSource();
    datalist1.DataBind();
  }
}

</script>
</head>
<body>
<form runat="server">
  <div align="center">
  <asp:DataList id="datalist1"
    CellPadding="4"
    DataKeyField="fileid"
    GridLines="Both"
    RepeatColumns="2"
    OnEditCommand="datalist1_Edit"
    OnUpdateCommand="datalist1_Update"
    OnCancelCommand="datalist1_Cancel"
    OnItemCommand="datalist1_Choice"
    runat="server">
    <HeaderTemplate>
      <p align="center"><%# Server.MapPath(".") %></p>
    </HeaderTemplate>
    <ItemTemplate>
      <%# DataBinder.Eval(Container.DataItem, "filename") %>
      ( <%# DataBinder.Eval(Container.DataItem, "filesize") %> Bytes )
      <asp:LinkButton Text="編集" CommandName="edit" runat="server" />
      <asp:LinkButton Text="選択" CommandName="choice" runat="server" />
    </ItemTemplate>
    <EditItemTemplate>
      <asp:TextBox id="filename" Text='<%# DataBinder.Eval(Container.DataItem, "filename") %>' runat="server" />
      <asp:LinkButton Text="更新" CommandName="update" runat="server" />
      <asp:LinkButton Text="キャンセル" CommandName="cancel" runat="server" />
    </EditItemTemplate>
    <SelectedItemTemplate>
      <b>
      <%# DataBinder.Eval(Container.DataItem, "filename") %>
      ( <%# DataBinder.Eval(Container.DataItem, "date") %> )
      </b>
      <asp:LinkButton Text="編集" CommandName="edit" runat="server" />
      <asp:LinkButton Text="選択" CommandName="choice" runat="server" />
    </SelectedItemTemplate>
    <FooterTemplate>
      <p align="right">
      <%# (new DirectoryInfo(Server.MapPath("."))).GetFiles().Length %>個のファイルがあります
      </p>
    </FooterTemplate>
  </asp:DataList>
  <asp:Label id="Message" runat="server" />
  </div>
</form>
</body>
</html>

リスト10.4 asp:DataListのテンプレート(sample09.aspx)
sample09.aspxのダウンロード(sample09.zip)


 リスト10.4では、カレント・ディレクトリ(sample09.aspxが格納されたディレクトリ)にあるファイルの一覧を取得して、これをデータソースとして利用している。そして、このデータソースをasp:DataListコントロールにデータ連結して、表としてページに出力する。出力された表のセルには、ファイル名とファイル・サイズ、それに[編集][選択]という2つのリンク・ボタンがそれぞれ出力される。これはItemTemplateが次のように指定されているためだ。

  <ItemTemplate>
    <%# DataBinder.Eval(Container.DataItem, "filename") %>
    ( <%# DataBinder.Eval(Container.DataItem, "filesize") %> Bytes )
    <asp:LinkButton Text="編集" CommandName="edit" runat="server" />
    <asp:LinkButton Text="選択" CommandName="choice" runat="server" />
  </ItemTemplate>

 ファイル名とファイル・サイズはデータ連結式によって出力され、リンク・ボタンはasp:LinkButtonを2つ並べて出力されている。なお、AlternatingItemTemplateは定義されていないため、すべての要素はItemTemplateでデータ連結される。

 この[編集]ボタンをクリックすると、セルの内容がファイル名を含むテキスト・ボックスに置き換えられる。また、ボタンも[更新]と[キャンセル]に置き換えられる。これは、[編集]ボタンをクリックすると、次のEditItemTemplateで出力されるようになるためだ。

  <EditItemTemplate>
    <asp:TextBox id="filename"
      Text='<%# DataBinder.Eval(Container.DataItem, "filename") %>'
       runat="server" />
    <asp:LinkButton Text="更新" CommandName="update" runat="server" />
    <asp:LinkButton Text="キャンセル" CommandName="cancel" runat="server" />
  </EditItemTemplate>

 また[選択]ボタンをクリックすると、ファイル名がボールド表示されるようになる。これはSelectedItemTemplateが次のように定義されているためだ。

  <SelectedItemTemplate>
    <b>
      <%# DataBinder.Eval(Container.DataItem, "filename") %>
      ( <%# DataBinder.Eval(Container.DataItem, "date") %> )
    </b>
    <asp:LinkButton Text="編集" CommandName="edit" runat="server" />
    <asp:LinkButton Text="選択" CommandName="choice" runat="server" />
  </SelectedItemTemplate>

 最後にHeaderTemplateとFooterTemplateを以下に示す。前述したようにHeaderTemplateとFooterTemplateにデータソースは連結されないため、ここでは単一値連結だけを行い、ヘッダにはカレント・ディレクトリのパスを、フッタにはカレント・ディレクトリにあるファイル数を出力している。

  <HeaderTemplate>
    <p align="center"><%# Server.MapPath(".") %></p>
  </HeaderTemplate>
  <FooterTemplate>
    <p align="right">
    <%# (new DirectoryInfo(Server.MapPath("."))).GetFiles().Length %>個のファイルがあります
    </p>
  </FooterTemplate>

Copyright© Digital Advantage Corp. All Rights Reserved.

ページトップに戻る