次の方法で共有


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

作成者: Scott Mitchell

PDF のダウンロード

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

はじめに

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

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

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

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

ItemDataBound イベント ハンドラーの使用

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

  • ItemCreatedDataListItem が作成された後に発生します
  • ItemDataBound は現在のレコードが DataListItem にバインドされた後に発生します

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

  1. DataList の DataBinding イベントが発生します

  2. データが DataList にバインドされます

    データ ソース内の各レコードに対して

    1. DataListItem オブジェクトを作成します
    2. ItemCreated イベントを発生させます
    3. レコードを DataListItem にバインドします
    4. ItemDataBound イベントを発生させます
    5. DataListItemItems コレクションに追加します

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

Note

勘の良い読者なら、DataList と Repeater がデータにバインドされている場合と GridView がデータにバインドされている場合とで、発生する一連の手順が若干異なっていることにお気付きになったかもしれません。 データ バインディング プロセスの最後で、GridView は DataBound イベントを発生させますが、DataList または Repeater のどちらのコントロールにもそのようなイベントはありません。 これは、DataList および Repeater のコントロールが、事前および事後レベルのイベント ハンドラー パターンが一般的になる前の ASP.NET 1.x 期間に作成されたためです。

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

DataList コントロールの場合、項目全体の書式設定の変更は、標準の FontForeColorBackColorCssClass などを含む DataListItem のスタイル関連のプロパティを使用して実装できます。 DataList のテンプレート内の特定の Web コントロールの書式設定に影響を与えるためには、プログラムによってこれらの Web コントロールのスタイルにアクセスして変更する必要があります。 これを実現する方法については、"データに基づくカスタム書式設定" のチュートリアルで説明しました。 Repeater コントロールと同様に、RepeaterItem クラスにはスタイル関連のプロパティがないため、ItemDataBound イベント ハンドラー内の RepeaterItem に対して行われるすべてのスタイル関連の変更は、テンプレート内の 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 に示すように、各製品の書式設定の違いは、背景色が交互に表示される点だけです。

The Products are Listed in the DataList Control

図 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 イベント ハンドラーの背後にある概念とセマンティクスは、"データに基づくカスタム書式設定" のチュートリアルの GridView の RowDataBound イベント ハンドラーで使用されているものと同じですが、構文は若干異なります。 ItemDataBound イベントが発生すると、データにバインドされた DataListItem が、(GridView の RowDataBound イベント ハンドラーと同様に e.Row ではなく) e.Item 経由で対応するイベント ハンドラーに渡されます。 DataList の ItemDataBound イベント ハンドラーは、ヘッダー行、フッター行、区切り行など、DataList に追加された "各" 行に対して発生します。 ただし、製品情報はデータ行にのみバインドされます。 そのため、ItemDataBound イベントを使用して DataList にバインドされたデータを検査する場合は、まずデータ項目を操作していることを確認する必要があります。 これは、DataListItemItemType プロパティを確認することで実現できます。このプロパティには、次の 8 つの値のいずれかを指定できます。

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

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

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

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

製品の価格が 20.00 ドル未満であることがわかったら、あとはその名前と価格を強調表示するだけです。 これを実現するには、まず、製品の名前と価格を表示する、ItemTemplate 内の Label コントロールをプログラムで参照する必要があります。 次に、黄色の背景を表示させる必要があります。 この書式設定情報は、Labels 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 ドル未満の製品は、名前と価格の両方が強調表示されています。

Those Products Less than $20.00 are Highlighted

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

Note

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

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

The Entire Product Item is Highlighted for Products Under $20.00

図 3: 20.00 ドル未満の製品の製品項目全体が強調表示されています (クリックするとフルサイズの画像が表示されます)

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

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

書式設定機能を説明するために、製品が製造中止された場合に、その製品名の横に [DISCONTINUED] というテキストが製品情報に含まれるようにしてみましょう。 また、価格が 20.00 ドル未満の場合は、(ItemDataBound イベント ハンドラーの例で行ったように) その価格を黄色で強調表示します。価格が 20.00 ドル以上の場合は、実際の価格を表示せず、代わりに "Please call for a price quote" (お見積もりはお電話でお問い合わせください) というテキストを表示します。 図 4 は、これらの書式設定ルールが適用された製品リストのスクリーン ショットを示しています。

Screenshot showing products listed in the DataList control, with the price of products costing more than $20.00 replaced with the text, 'Please call for a price quote.'

図 4: 高価な製品の場合、価格は "Please call for a price quote" というテキストに置き換えられます (クリックするとフルサイズの画像が表示されます)

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

この例では、2 つの書式設定関数が必要です。1 つは必要に応じて製品名とテキスト [DISCONTINUED] を表示する関数、もう 1 つは 20.00 ドル未満の場合は強調表示された価格を表示し、それ以外の場合は "Please call for a price quote" というテキストを表示する関数です。 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 メソッドは、productName および discontinued データ フィールドの値をスカラー値として受け入れるのに対し、DisplayPrice メソッドは (unitPrice スカラー値ではなく) ProductsRow インスタンスを受け入れることに注意してください。 どちらの方法でも機能します。ただし、書式設定関数がデータベースの NULL 値を含む可能性のあるスカラー値 (UnitPrice など) を扱う場合 (ProductName または Discontinued はどちらも NULL 値を許可しない)、これらのスカラー入力の処理には特別な注意が必要です。

特に、入力パラメーターは 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 の ItemTemplate から書式設定関数を呼び出す

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

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

DataList の ItemTemplate では、ProductNameLabel Label 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 ドルを超える製品の価格は "Please call for a price quote" というテキストに置き換えらています。

Screenshot showing products listed in the DataList control, with the price of products costing more than $20.00 replaced with the text, 'Please call for a price quote', and the text '[DISCONTINUED]' appended to the name of discontinued products.

図 5: 高価な製品の場合、価格は "Please call for a price quote"というテキストに置き換えられています (クリックするとフルサイズの画像が表示されます)

まとめ

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

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

プログラミングに満足!

著者について

Scott Mitchell は、ASP/ASP.NET に関する 7 冊の書籍の著者であり、4GuysFromRolla.com の設立者でもあります。1998 年以降、Microsoft の Web テクノロジを活用した業務を行っています。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズは24時間で2.0 ASP.NET 自分自身を教えています。 にアクセスするか、ブログを使用して にアクセスmitchell@4GuysFromRolla.comできます。これは でhttp://ScottOnWriting.NET見つけることができます。

特別な感謝

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