次の方法で共有


データに基づいて DataList と Repeater を書式設定する (C#)

スコット・ミッチェル著

PDF をダウンロードする

このチュートリアルでは、テンプレート内の書式設定関数を使用するか、DataBound イベントを処理することによって、DataList コントロールと Repeater コントロールの外観を書式設定する方法の例を順を追って説明します。

イントロダクション

前のチュートリアルで説明したように、DataList には、外観に影響を与えるスタイル関連のプロパティが多数用意されています。 特に、DataList の HeaderStyleItemStyleAlternatingItemStyleSelectedItemStyle プロパティに既定の CSS クラスを割り当てる方法について説明しました。 これらの 4 つのプロパティに加えて、DataList には、 FontForeColorBackColorBorderWidthなど、いくつかのスタイル関連のプロパティが含まれています。 Repeater コントロールには、スタイル関連のプロパティは含まれません。 このようなスタイル設定は、Repeater のテンプレートのマークアップ内で直接行う必要があります。

ただし、多くの場合、データの書式設定方法はデータ自体によって異なります。 たとえば、製品を一覧表示するときに、製品情報が廃止された場合は薄い灰色のフォント色で表示したり、 UnitsInStock 値が 0 の場合は強調表示したりできます。 前のチュートリアルで説明したように、GridView、DetailsView、FormView には、データに基づいて外観を書式設定する 2 つの異なる方法が用意されています。

  • DataBound イベントは、適切なDataBound イベントのイベント ハンドラーを作成します。これは、データが各項目にバインドされた後に発生します (GridView の場合はRowDataBoundイベントです。DataList と Repeater の場合はItemDataBound イベントです)。 そのイベント ハンドラーでは、バインドされたデータを検討し、書式設定の決定を行うことができます。 この手法は、 データに基づくカスタム書式設定 のチュートリアルで確認しました。
  • DetailsView コントロールまたは GridView コントロールの TemplateFields を使用する場合、または FormView コントロールのテンプレートを使用する場合は、テンプレートの書式設定関数を、ASP.NET ページの分離コード クラス、ビジネス ロジック レイヤー、または Web アプリケーションからアクセスできるその他のクラス ライブラリに追加できます。 この書式設定関数は任意の数の入力パラメーターを受け取ることができますが、テンプレートでレンダリングするには HTML を返す必要があります。 書式設定関数は、GridView コントロールで TemplateFields を利用する方法のチュートリアルで最初に検討されました。

これらの両方の書式設定手法は、DataList コントロールと Repeater コントロールで使用できます。 このチュートリアルでは、両方のコントロールに対して両方の手法を使用する例を順を追って説明します。

ItemDataBoundEvent ハンドラーの使用

データ がデータ ソース コントロールから、またはプログラムによってコントロールの DataSource プロパティにデータを割り当て、その DataBind() メソッドを呼び出すことによって、DataList にバインドされると、DataList DataBinding イベントが発生し、データ ソースが列挙され、各データ レコードが DataList にバインドされます。 データ ソース内の各レコードに対して、DataList は現在のレコードにバインドされる DataListItem オブジェクトを作成します。 このプロセス中に、DataList は次の 2 つのイベントを発生させます。

  • ItemCreatedDataListItemが作成されたその後に発生する
  • ItemDataBoundDataListItem に現在のレコードをバインドした後に発火します。

次の手順では、DataList コントロールのデータ バインディング プロセスについて説明します。

  1. DataList の DataBinding イベント が発火する

  2. データが DataList にバインドされている

    データ ソース内の各レコードについて

    1. DataListItem オブジェクトを作成します
    2. ItemCreated イベントを発火する
    3. レコードを DataListItem に結びつける
    4. ItemDataBound イベントを発火する
    5. DataListItem コレクションにItemsを追加する

Repeater コントロールにデータをバインドすると、まったく同じ一連の手順が進行します。 唯一の違いは、インスタンス DataListItem 作成されるのではなく、Repeater が RepeaterItemを使用することです。

DataList と Repeater がデータにバインドされている場合と GridView がデータにバインドされている場合に発生する一連の手順の間にわずかな異常が発生している可能性があります。 データ バインディング プロセスの末尾で、GridView は DataBound イベントを発生させます。ただし、DataList コントロールも Repeater コントロールにもそのようなイベントはありません。 これは、DataList コントロールと Repeater コントロールが ASP.NET 1.x 時代に作成され、その頃にはまだイベント ハンドラー パターンが一般的になっていなかったからです。

GridView と同様に、データに基づいて書式設定するオプションの 1 つは、 ItemDataBound イベントのイベント ハンドラーを作成することです。 このイベント ハンドラーは、 DataListItem または RepeaterItem にバインドされたデータを検査し、必要に応じてコントロールの書式設定に影響します。

DataList コントロールでは、標準のDataListItemFontForeColorBackColorなど、CssClassのスタイル関連プロパティを使用して、アイテム全体の書式設定の変更を実装できます。 DataList のテンプレート内の特定の Web コントロールの書式設定に影響を与えるためには、プログラムによってこれらの Web コントロールのスタイルにアクセスして変更する必要があります。 これを実現する方法については、「 データに基づくカスタム書式設定」 チュートリアルを参照してください。 Repeater コントロールと同様に、RepeaterItem クラスにはスタイル関連のプロパティがないため、RepeaterItem イベント ハンドラーのItemDataBoundに加えられたスタイル関連のすべての変更は、テンプレート内の Web コントロールにプログラムでアクセスして更新することによって行う必要があります。

DataList と Repeater の ItemDataBound 書式設定手法は実質的に同じであるため、この例では DataList の使用に重点を置きます。

手順 1: DataList に製品情報を表示する

書式設定について心配する前に、まず DataList を使用して製品情報を表示するページを作成しましょう。 前の チュートリアル では、 ItemTemplate が各製品の名前、カテゴリ、仕入先、単位あたりの数量、および価格を表示する DataList を作成しました。 このチュートリアルでは、この機能を繰り返します。 これを実現するには、DataList とその ObjectDataSource を最初から再作成するか、前のチュートリアル (Basics.aspx) で作成したページからこれらのコントロールをコピーして、このチュートリアルのページに貼り付けます (Formatting.aspx)。

DataList と ObjectDataSource の機能を Basics.aspx から Formatting.aspx にレプリケートしたら、少し時間を取って DataList の ID プロパティを DataList1 からよりわかりやすい ItemDataBoundFormattingExampleに変更します。 次に、ブラウザーで DataList を表示します。 図 1 に示すように、各製品の書式設定の違いは、背景色が交互に表示される点だけです。

DataList コントロールに製品が表示される

図 1: DataList コントロールに製品が一覧表示されます (フルサイズの画像を表示する をクリックします)。

このチュートリアルでは、価格が $20.00 未満の製品の名前と単価の両方が黄色で強調表示されるように DataList を書式設定します。

手順 2: プログラムによって ItemDataBound イベント ハンドラー内のデータの値を決定する

価格が $20.00 以下の製品にのみカスタム書式が適用されるため、各製品の価格を決定できる必要があります。 DataList にデータをバインドする場合、DataList はデータ ソース内のレコードを列挙し、レコードごとに DataListItem インスタンスを作成し、データ ソース レコードを DataListItemにバインドします。 特定のレコードのデータが現在の DataListItem オブジェクトにバインドされると、DataList ItemDataBound イベントが発生します。 このイベントのイベント ハンドラーを作成して、現在の DataListItem のデータ値を検査し、それらの値に基づいて、必要な書式設定の変更を行うことができます。

DataList の ItemDataBound イベントを作成し、次のコードを追加します。

protected void ItemDataBoundFormattingExample_ItemDataBound
    (object sender, DataListItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item ||
        e.Item.ItemType == ListItemType.AlternatingItem)
    {
        // Programmatically reference the ProductsRow instance bound
        // to this DataListItem
        Northwind.ProductsRow product =
            (Northwind.ProductsRow)((System.Data.DataRowView)e.Item.DataItem).Row;
        // See if the UnitPrice is not NULL and less than $20.00
        if (!product.IsUnitPriceNull() && product.UnitPrice < 20)
        {
            // TODO: Highlight the product's name and price
        }
    }
}

DataList の ItemDataBound イベント ハンドラーの背後にある概念とセマンティクスは、Data にRowDataBoundチュートリアルの GridView イベント ハンドラーで使用されるものと同じですが、構文は若干異なります。 ItemDataBound イベントが発生すると、データにバインドされたDataListItemは、(GridView のe.Item イベント ハンドラーと同様に、e.Rowではなく) RowDataBoundを介して対応するイベント ハンドラーに渡されます。 DataList ItemDataBound イベント ハンドラーは、ヘッダー行、フッター行、区切り文字行など、DataList に追加された 各行 に対して発生します。 ただし、製品情報はデータ行にのみバインドされます。 そのため、 ItemDataBound イベントを使用して DataList にバインドされたデータを検査する場合は、まずデータ項目を操作していることを確認する必要があります。 これは、DataListItemのいずれかを持つことができますItemTypeプロパティを確認することで実現できます。

  • AlternatingItem
  • EditItem
  • Footer
  • Header
  • Item
  • Pager
  • SelectedItem
  • Separator

ItemAlternatingItem``DataListItemの両方が、DataList のデータ項目を構成します。 ItemまたはAlternatingItemを使用していると仮定すると、現在のProductsRowにバインドされた実際のDataListItem インスタンスにアクセスします。 DataListItemDataItem プロパティには、DataRowView オブジェクトへの参照が含まれています。Row プロパティは、実際のProductsRow オブジェクトへの参照を提供します。

次に、 ProductsRow インスタンスの UnitPrice プロパティを確認します。 Products テーブルの UnitPrice フィールドでは値をNULLできるため、UnitPrice プロパティにアクセスする前に、まず、NULL メソッドを使用してIsUnitPriceNull()値があるかどうかを確認する必要があります。 UnitPrice値がNULLされていない場合は、$20.00 未満かどうかを確認します。 実際に $20.00 以下の場合は、カスタム書式を適用する必要があります。

手順 3: 製品名と価格を強調表示する

製品の価格が $20.00 未満であることがわかったら、残っているのは、その名前と価格を強調表示するだけです。 これを実現するには、まず、製品の名前と価格を表示する ItemTemplate の Label コントロールをプログラムで参照する必要があります。 次に、黄色の背景を表示する必要があります。 この書式設定情報は、ラベル BackColor プロパティ (LabelID.BackColor = Color.Yellow) を直接変更することで適用できます。ただし、理想的には、すべての表示関連事項をカスケード スタイルシートで表す必要があります。 実際には、 Styles.css - AffordablePriceEmphasisで定義されている目的の書式設定を提供するスタイルシートが既に用意されています。これは、 データに基づくカスタム書式設定 のチュートリアルで作成および説明されています。

書式設定を適用するには、次のコードに示すように、2 つの Label Web コントロール CssClass プロパティを AffordablePriceEmphasisに設定します。

// Highlight the product name and unit price Labels
// First, get a reference to the two Label Web controls
Label ProductNameLabel = (Label)e.Item.FindControl("ProductNameLabel");
Label UnitPriceLabel = (Label)e.Item.FindControl("UnitPriceLabel");
// Next, set their CssClass properties
if (ProductNameLabel != null)
    ProductNameLabel.CssClass = "AffordablePriceEmphasis";
if (UnitPriceLabel != null)
    UnitPriceLabel.CssClass = "AffordablePriceEmphasis";

ItemDataBound イベント ハンドラーが完了したら、ブラウザーのFormatting.aspx ページに再びアクセスします。 図2が示すように、価格が20.00ドル未満の製品は、名前と価格の両方が強調表示されています。

20.00 ドル未満の製品が強調表示されている

図 2: $20.00 未満の製品が強調表示されている (フルサイズの画像を表示する をクリックします)

DataList は HTML <table>としてレンダリングされるため、その DataListItem インスタンスには、アイテム全体に特定のスタイルを適用するように設定できるスタイル関連のプロパティがあります。 たとえば、価格が $20.00 未満のときにアイテム 全体 を黄色で強調表示する場合は、Labels を参照するコードを置き換え、その CssClass プロパティを次のコード行に設定できます: e.Item.CssClass = "AffordablePriceEmphasis" (図 3 を参照)。

ただし、Repeater コントロールを構成する RepeaterItem は、このようなスタイル レベルのプロパティを提供しません。 そのため、Repeater にカスタム書式を適用するには、図 2 のように、Repeater のテンプレート内の Web コントロールにスタイル プロパティを適用する必要があります。

$20.00 以下の製品では、製品アイテム全体が強調表示されます

図 3: $20.00 未満の製品の製品アイテム全体が強調表示されている (フルサイズの画像を表示する をクリックします)

テンプレート内からの書式設定関数の使用

GridView コントロールチュートリアルの TemplateFields の使用チュートリアルでは、GridView TemplateField 内で書式設定関数を使用して、GridView の行にバインドされたデータに基づいてカスタム書式を適用する方法について説明しました。 書式設定関数は、テンプレートから呼び出すことができるメソッドであり、その代わりに出力される HTML を返します。 書式設定関数は、ASP.NET ページの分離コード クラスに配置することも、 App_Code フォルダーまたは別のクラス ライブラリ プロジェクト内のクラス ファイルに一元化することもできます。 ASP.NET ページの分離コード クラスから書式設定関数を移動することは、複数の ASP.NET ページや他の ASP.NET Web アプリケーションで同じ書式設定関数を使用する場合に最適です。

フォーマット機能を示すために、製品が廃版の場合は、製品名の横に [DISCONTINUED] というテキストを含めてみましょう。 また、価格が $20.00 ( ItemDataBound イベント ハンドラーの例で行ったように) より小さい場合は黄色で強調表示します。価格が $20.00 以上の場合は、実際の価格を表示せず、代わりにテキストを表示します。価格見積もりを呼び出してください。 図 4 は、これらの書式設定ルールが適用された製品の一覧のスクリーン ショットを示しています。

DataList コントロールにリストされている製品を示すスクリーンショット。20.00 ドルを超える製品の価格が、

図 4: 高価な製品の場合、価格はテキストに置き換えられます。価格の見積もりを呼び出してください (フルサイズの画像を表示するにはクリックしてください)

手順 1: 書式設定関数を作成する

この例では、2 つの書式設定関数が必要です。1 つは、必要に応じて製品名とテキスト [DISCONTINUED] を表示し、もう 1 つは $20.00 未満の場合は強調表示された価格を表示し、それ以外の場合は価格見積もりを呼び出してください。 ASP.NET ページの分離コード クラスでこれらの関数を作成し、 DisplayProductNameAndDiscontinuedStatus および DisplayPriceに名前を付けます。 どちらのメソッドも、文字列としてレンダリングするために HTML を返す必要があります。また、ASP.NET ページの宣言構文部分から呼び出すには、両方とも Protected (または Public) としてマークする必要があります。 これら 2 つのメソッドのコードは次のとおりです。

protected string DisplayProductNameAndDiscontinuedStatus
    (string productName, bool discontinued)
{
    // Return just the productName if discontinued is false
    if (!discontinued)
        return productName;
    else
        // otherwise, return the productName appended with the text "[DISCONTINUED]"
        return string.Concat(productName, " [DISCONTINUED]");
}
protected string DisplayPrice(Northwind.ProductsRow product)
{
    // If price is less than $20.00, return the price, highlighted
    if (!product.IsUnitPriceNull() && product.UnitPrice < 20)
        return string.Concat("<span class=\"AffordablePriceEmphasis\">",
                              product.UnitPrice.ToString("C"), "</span>");
    else
        // Otherwise return the text, "Please call for a price quote"
        return "<span>Please call for a price quote</span>";
}

DisplayProductNameAndDiscontinuedStatus メソッドでは、productNamediscontinuedのデータ フィールドの値をスカラー値として受け入れますが、DisplayPrice メソッドは (ProductsRow スカラー値ではなく) unitPrice インスタンスを受け取ります。 どちらの方法でも機能します。ただし、書式設定関数が、データベースNULL値を含むことができるスカラー値(例えばUnitPrice; ProductNameDiscontinuedNULL値を許可しない)を含む場合は、これらのスカラー入力を特に注意して扱う必要があります。

特に、入力パラメーターは Object 型である必要があります。これは、受信値が想定されるデータ型ではなく DBNull インスタンスである可能性があるためです。 さらに、受信値がデータベースの NULL 値であるかどうかを確認する必要があります。 つまり、 DisplayPrice メソッドで価格をスカラー値として受け入れたい場合は、次のコードを使用する必要があります。

protected string DisplayPrice(object unitPrice)
{
    // If price is less than $20.00, return the price, highlighted
    if (!Convert.IsDBNull(unitPrice) && ((decimal) unitPrice) < 20)
        return string.Concat("<span class=\"AffordablePriceEmphasis\">",
                              ((decimal) unitPrice).ToString("C"), "</span>");
    else
        // Otherwise return the text, "Please call for a price quote"
        return "<span>Please call for a price quote</span>";
}

unitPrice入力パラメーターはObject型であり、unitPriceDBNullされているかどうかを確認するために条件付きステートメントが変更されていることに注意してください。 さらに、 unitPrice 入力パラメーターは Objectとして渡されるため、10 進値にキャストする必要があります。

手順 2: DataList s ItemTemplate から書式設定関数を呼び出す

ASP.NET ページの分離コード クラスに書式設定関数が追加されたので、残っているのは DataList の ItemTemplateからこれらの書式設定関数を呼び出す方法です。 テンプレートから書式設定関数を呼び出すには、データ バインド構文内に関数呼び出しを配置します。

<%# MethodName(inputParameter1, inputParameter2, ...) %>

DataList のItemTemplateProductNameLabel ラベル Web コントロールでは、現在、Text プロパティに<%# Eval("ProductName") %>の結果を割り当てることで、製品の名前が表示されます。 名前とテキスト [DISCONTINUED] を表示するには、必要に応じて宣言構文を更新し、代わりに Text プロパティに DisplayProductNameAndDiscontinuedStatus メソッドの値を割り当てます。 その場合は、 Eval("columnName") 構文を使用して、製品名と廃止された値を渡す必要があります。 EvalObject型の値を返しますが、 DisplayProductNameAndDiscontinuedStatus メソッドは型 String および Boolean の入力パラメーターを受け取ります。したがって、 Eval メソッドによって返される値を、次のように想定される入力パラメーター型にキャストする必要があります。

<h4>
    <asp:Label ID="ProductNameLabel" runat="server"
        Text='<%# DisplayProductNameAndDiscontinuedStatus((string) Eval("ProductName"),
              (bool) Eval("Discontinued")) %>'>
    </asp:Label>
</h4>

価格を表示するには、製品の名前と [DISCONTINUED] テキストを表示する場合と同様に、 UnitPriceLabel Label Text プロパティを DisplayPrice メソッドによって返される値に設定するだけです。 ただし、 UnitPrice をスカラー入力パラメーターとして渡す代わりに、 ProductsRow インスタンス全体を渡します。

<asp:Label ID="UnitPriceLabel" runat="server"
    Text='<%# DisplayPrice((Northwind.ProductsRow)
          ((System.Data.DataRowView) Container.DataItem).Row) %>'>
</asp:Label>

書式設定関数の呼び出しが行われたので、ブラウザーで進行状況を確認します。 画面は図 5 のようになります。[DISCONTINUED] というテキストを含む廃止された製品と、価格が 20.00 ドルを超える製品の価格がテキストに置き換えられました。価格見積もりを呼び出してください。

DataList コントロールにリストされている製品を示すスクリーンショット。20.00 ドルを超える製品の価格が、

図 5: 高価な製品の場合、価格はテキストに置き換えられます。価格の見積もりを呼び出してください (フルサイズの画像を表示するにはクリックしてください)

概要

データに基づいて DataList コントロールまたは Repeater コントロールの内容を書式設定するには、2 つの手法を使用します。 最初の手法は、データ ソース内の各レコードが新しいItemDataBoundまたはDataListItemにバインドされるときに発生する、RepeaterItem イベントのイベント ハンドラーを作成することです。 ItemDataBound イベント ハンドラーでは、現在の項目のデータを調べてから、テンプレートの内容に書式設定を適用したり、DataListItemの場合はアイテム全体に書式設定を適用したりすることができます。

または、書式設定関数を使用してカスタム書式設定を実現することもできます。 書式設定関数は、その代わりに出力する HTML を返す DataList または Repeater のテンプレートから呼び出すことができるメソッドです。 多くの場合、書式設定関数によって返される HTML は、現在の項目にバインドされている値によって決まります。 これらの値は、スカラー値として、または項目にバインドされているオブジェクト全体 ( ProductsRow インスタンスなど) を渡すことによって、書式設定関数に渡すことができます。

プログラミングに満足!

著者について

7 冊の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジを使用しています。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズ・ティーチ・セルフ ASP.NET 24時間で2.0です。 彼には mitchell@4GuysFromRolla.comで連絡できます。

特別な感謝

このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は、Yaakov Ellis、Randy Schmidt、Liz Shulok でした。 今後の MSDN の記事を確認することに関心がありますか? その場合は、mitchell@4GuysFromRolla.comにメッセージを送ってください。