ItemStyleコントロールやSelectedItemStyleコントロールを使えば、セルにスタイルを設定できるが、それは静的なものでしかないし、細かなスタイルまで設定することはできない。もっと柔軟にスタイルを制御するには、イベント・ハンドラを定義して、プログラム・コードからスタイルを設定する必要がある。
プログラムからスタイルを設定するサンプルをリスト13-3に示す。このサンプル・プログラムを実行すると、例によってファイルの一覧がasp:DataGridコントロールを使って一覧表示されるが、ファイルのサイズが3kbyteを超える場合はアイテムの文字色(ForeColor)が赤に設定されるようになっている。また、同様に5kbyteを超える場合は、アイテム(=行)ではなく、ファイル・サイズが表示されているセルだけにスタイルを設定し、赤地(BackColor="red")に白文字(ForeColor="white")で表示される。
<%@ PAGE LANGUAGE="C#" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Drawing" %>
<html>
<head>
<script runat="server">
void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
datagrid1.DataSource = CreateDataSource();
datagrid1.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 datagrid1_DataBound(
object sender, DataGridItemEventArgs e) {
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem) {
if (e.Item.DataItem != null) {
DataRow row = ((DataRowView)e.Item.DataItem).Row;
long size = (long) row["filesize"];
if (size > 3072) {
e.Item.ForeColor = Color.FromName("Red");
}
if (size > 5120) {
TableCell cell = (TableCell) e.Item.Controls[1];
cell.BackColor = Color.FromName("Red");
cell.ForeColor = Color.FromName("White");
}
}
}
}
</script>
</head>
<body bgcolor="#333366">
<form runat="server">
<div align="center">
<asp:DataGrid id="datagrid1"
AutoGenerateColumns="false"
GridLines="None"
Width="100%"
CellSpacing="1"
BorderWidth="5"
BorderColor="#000080"
OnItemDataBound="datagrid1_DataBound"
runat="server">
<HeaderStyle BackColor="#000080" ForeColor="white" />
<ItemStyle ForeColor="black" BackColor="#ffffcc" />
<AlternatingItemStyle
ForeColor="black" BackColor="#ffff66" />
<SelectedItemStyle
ForeColor="white" BackColor="#000080" />
<Columns>
<asp:BoundColumn
HeaderText="ファイル名" DataField="filename" />
<asp:BoundColumn HeaderText="サイズ"
DataField="filesize" ItemStyle-Width="10%"
ItemStyle-HorizontalAlign="right" />
<asp:BoundColumn HeaderText="更新日時"
DataField="date" ItemStyle-Width="30%" />
<asp:ButtonColumn CommandName="select"
Text="選択" ItemStyle-Width="10%" />
</Columns>
</asp:DataGrid>
<asp:Label id="Message" runat="server" />
</div>
</form>
</body>
</html>
■ItemDataBoundイベント
このように動的にスタイルを設定するには、ItemDataBoundイベントを利用する。ItemDataBoundイベントは、アイテムがデータ連結されるたびに発生するため、各アイテムの状態やデータソースの値を調べ、それに応じてアイテムの設定を行うために利用できる。
<asp:DataGrid id="datagrid1"
OnItemDataBound="datagrid1_DataBound"
runat="server">
<asp:DataList id="datalist1"
OnItemDataBound="datalist1_DataBound"
runat="server">
ItemDataBoundイベントのシグネチャは以下のように宣言されている。DataListItemEventArgsとDataGridItemEventArgsには、どちらにも同じくItemプロパティがあり、このプロパティを通して、これからデータ連結されるアイテム(データ連結された要素)の値を調べたり、スタイルを設定したりすることができる。
asp:DataListコントロール void DataListItemEventHandler(object sender, DataListItemEventArgs e)
asp:DataGridコントロール void DataGridItemEventHandler(object sender, DataGridItemEventArgs e)
asp:DataListコントロールのe.ItemプロパティはDataListItemオブジェクト、asp:DataGridコントロールのe.ItemプロパティはDataGridItemオブジェクトというように異なるが、どちらも基本スタイルを持つWebControlクラスから継承して定義されたサブクラスであるため、e.Item.ForeColorなどとして基本スタイルにアクセスすることができる。また、両クラスには表13-7に示す共通のプロパティが定義されていて、これを通してデータ連結されるアイテムにアクセスできる。
型 | プロパティ名 | 内容 |
---|---|---|
object | DataItem | データ連結された要素 |
int | ItemIndex | 要素につけられたインデックス |
ListItemType | ItemType | アイテムが連結されるテンプレート種 |
表13-7 DataGridItemクラスとDataListItemクラスのプロパティ |
■データ連結されるアイテムを取得する
それでは、具体的にスタイルを設定する手順を見ていこう。
リスト13-3ではまず最初に、e.Item.ItemTypeの値を調べ、それがListItemType.Item(ItemTemplateに対応)かListItemType.AlternatingItem(AlternatingItemTemplateに対応)か調べている。ItemDataBoundイベントはHeaderItemやFooterItemの連結時にも発生するため、こうしてスタイルを適用すべきアイテムなのか判断しているのである。
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem) {
……
}
次に、e.Item.DataItemプロパティへアクセスし、データソースから値を取り出す。このためには、データ連結の解説の中でも述べたように、objectオブジェクトとして定義されているDataItemプロパティを、データソースの型に応じて、適切なクラスへとキャストしなければならない。例えば、リスト13-3ではDataViewオブジェクトをデータソースに利用しているので、DataItemプロパティにはDataRowViewオブジェクトが格納されている。そこで以下のようにしてキャストし、目的の値が格納されているDataRowオブジェクトを取り出す。データソースとDataItemの関係について詳しくは、すでにデータ連結の回に解説しているので、そちらを参照してほしい。
DataRow row = ((DataRowView)e.Item.DataItem).Row;
こうしてDataRowオブジェクトが入手できれば、あとはフィールド名を指定して、インデクサにアクセスすれば、目的の値を入手することができる。
long size = (long) row["filesize"];
■アイテムへのスタイルの設定
ファイル・サイズを取得したら、この値が3072byte以上であれば、アイテムが連結される行の文字色を赤に設定する。この処理は以下のように記述できる。DataGridItemクラス(e.Item)は、TableRowクラスを通してWebControlクラスの間接サブクラスとして定義されているため、e.Itemを通してスタイルを設定すると、テーブルの行全体の文字色が赤に設定される。
if (size > 3072) {
e.Item.ForeColor = Color.FromName("Red");
}
なお、全く同じ処理をasp:DataListコントロールで実行すると、テーブルの行ではなく、特定のセルに対して文字色が設定される。asp:DataListコントロールでは、各アイテムが1つのセルに出力されるためである。
■セルへのスタイルの設定
asp:DataListコントロールならば以上の解説で十分だが、asp:DataGridコントロールではe.Itemへの操作だけでは行単位での操作になってしまい、セルごとにスタイルを制御することはできない。asp:DataGridコントロールで特定のセルにスタイルを設定するには、e.Item.Controlsコレクション・プロパティへアクセスし、特定のTableCellオブジェクトを取得する必要がある。
この手順を解説する前に、テーブルの構造を簡単に解説しておこう。HTMLのテーブルは、図13-4に示すようにテーブル全体を囲むtableエレメントがあり、その子要素として各行を表すtrエレメントが、さらにtrエレメントの子要素として各セルに対応するtdエレメントが記述される。
ASP.NETではこの構造が図13-5に示すオブジェクトで構成される。クラス名の後ろにあるのは、各クラスの主要プロパティである。TableクラスにはTableRowオブジェクトを格納したRowsコレクション・プロパティがあり、TableRowクラスにはTableCellオブジェクトを格納したCellsコレクションがある。こうしてプロパティをたぐっていけば、目的のセルへアクセスできるというわけである。Tableクラス、TableRowクラス、TableCellクラスはいずれもWebControlクラスのサブクラスであるため、基本スタイルを設定可能である。
従って、2つ目のカラムに表示されているファイル・サイズを赤地に白文字で表示するには、以下の処理を行えばよい。
if (size > 5120) {
TableCell cell = (TableCell) e.Item.Cells[1];
cell.BackColor = Color.FromName("Red");
cell.ForeColor = Color.FromName("White");
}
次回後編では、asp:DataGridコントロールに固有のいくつかのスタイルと、ASP.NETからではアクセスできないCSSのプロパティ利用法などについて解説する予定だ。
Copyright© Digital Advantage Corp. All Rights Reserved.