データに基づいて DataList と Repeater を書式設定する (VB)
このチュートリアルでは、テンプレート内の書式設定関数を使用して、または DataBound イベントを処理して、DataList コントロールと Repeater コントロールの外観を書式設定する方法の例を順を追って説明します。
はじめに
前のチュートリアルで説明したように、DataList には、その外観に影響を与えるスタイル関連のプロパティが多数用意されています。 特に、既定の CSS クラスを DataList のプロパティ HeaderStyle
、ItemStyle
、AlternatingItemStyle
、SelectedItemStyle
に割り当てる方法を確認しました。 DataList には、これら 4 つのプロパティに加えて、Font
、ForeColor
、BackColor
、BorderWidth
など、スタイルに関連するプロパティが多数含まれています。 Repeater コントロールには、スタイル関連のプロパティは含まれません。 このようなスタイル設定は、Repeater のテンプレートのマークアップ内で直接行う必要があります。
ただし、多くの場合、データをどのように書式設定するかはデータ自体に依存します。 たとえば、製品を一覧表示するときに、製品情報を、製品が廃止された場合は薄い灰色のフォント色で表示したり、UnitsInStock
値がゼロの場合は強調表示したりすることができます。 前のチュートリアルで説明したように、GridView、DetailsView、FormView には、データに基づいて外観を書式設定する 2 つの異なる方法が用意されています。
DataBound
DataBound イベントは、適切な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 つのイベントを発生させます。
ItemCreated
はDataListItem
が作成された後に発生しますItemDataBound
は現在のレコードがDataListItem
にバインドされた後に発生します
次の手順では、DataList コントロールのデータ バインディング プロセスについて説明します。
DataList の
DataBinding
イベントが発生しますデータが DataList にバインドされます
データ ソース内の各レコードに対して
DataListItem
オブジェクトを作成しますItemCreated
イベントを発生させます- レコードを
DataListItem
にバインドします ItemDataBound
イベントを発生させますDataListItem
をItems
コレクションに追加します
Repeater コントロールにデータをバインドすると、まったく同じ一連の手順が実行されます。 唯一の違いは、DataListItem
インスタンスが作成される代わりに、Repeater では RepeaterItem
が使用されることです。
Note
勘の良い読者なら、DataList と Repeater がデータにバインドされている場合と GridView がデータにバインドされている場合とで、発生する一連の手順が若干異なっていることにお気付きになったかもしれません。 データ バインディング プロセスの最後で、GridView は DataBound
イベントを発生させますが、DataList または Repeater のどちらのコントロールにもそのようなイベントはありません。 これは、DataList および Repeater のコントロールが、事前および事後レベルのイベント ハンドラー パターンが一般的になる前の ASP.NET 1.x 期間に作成されたためです。
GridView と同様に、データに基づいて書式設定するための 1 つのオプションは、ItemDataBound
イベントのイベント ハンドラーを作成することです。 このイベント ハンドラーは、DataListItem
または RepeaterItem
にバインドされたばかりのデータを検査し、必要に応じてコントロールの書式設定に影響を与えます。
DataList コントロールの場合、項目全体の書式設定の変更は、標準の Font
、ForeColor
、BackColor
、CssClass
などを含む 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 に示すように、各製品の書式設定の違いは、背景色が交互に表示される点だけです。
図 1: DataList コントロールに製品が一覧表示されています (クリックするとフルサイズの画像が表示されます)
このチュートリアルでは、価格が 20.00 ドル未満の製品の名前と単価の両方が黄色で強調表示されるように DataList を書式設定します。
手順 2: プログラムによって ItemDataBound イベント ハンドラー内のデータの値を決定する
価格が 20.00 ドル未満の製品のみにカスタム書式が適用されるため、各製品の価格を決定できる必要があります。 データを DataList にバインドすると、DataList はデータ ソース内のレコードを列挙し、レコードごとに DataListItem
インスタンスを作成して、データ ソース レコードを DataListItem
にバインドします。 特定のレコードのデータが現在の DataListItem
オブジェクトにバインドされると、DataList の ItemDataBound
イベントが発生します。 このイベントのイベント ハンドラーを作成して、現在の DataListItem
のデータ値を検査し、それらの値に基づいて必要な書式設定の変更を行うことができます。
DataList の ItemDataBound
イベントを作成し、次のコードを追加します。
Protected Sub ItemDataBoundFormattingExample_ItemDataBound _
(sender As Object, e As DataListItemEventArgs) _
Handles ItemDataBoundFormattingExample.ItemDataBound
If e.Item.ItemType = ListItemType.Item OrElse _
e.Item.ItemType = ListItemType.AlternatingItem Then
' Programmatically reference the ProductsRow instance
' bound to this DataListItem
Dim product As Northwind.ProductsRow = _
CType(CType(e.Item.DataItem, System.Data.DataRowView).Row, _
Northwind.ProductsRow)
' See if the UnitPrice is not NULL and less than $20.00
If Not product.IsUnitPriceNull() AndAlso product.UnitPrice < 20 Then
' TODO: Highlight the product's name and price
End If
End If
End Sub
DataList の ItemDataBound
イベント ハンドラーの背後にある概念とセマンティクスは、"データに基づくカスタム書式設定" のチュートリアルの GridView の RowDataBound
イベント ハンドラーで使用されているものと同じですが、構文は若干異なります。 ItemDataBound
イベントが発生すると、データにバインドされた DataListItem
が、(GridView の RowDataBound
イベント ハンドラーと同様に e.Row
ではなく) e.Item
経由で対応するイベント ハンドラーに渡されます。 DataList の ItemDataBound
イベント ハンドラーは、ヘッダー行、フッター行、区切り行など、DataList に追加された "各" 行に対して発生します。 ただし、製品情報はデータ行にのみバインドされます。 そのため、ItemDataBound
イベントを使用して DataList にバインドされたデータを検査する場合は、まずデータ項目を操作していることを確認する必要があります。 これは、DataListItem
の ItemType
プロパティを確認することで実現できます。このプロパティには、次の 8 つの値のいずれかを指定できます。
AlternatingItem
EditItem
Footer
Header
Item
Pager
SelectedItem
Separator
Item
と AlternatingItem``DataListItem
はどちらも DataList のデータ項目を構成します。 Item
または AlternatingItem
を操作していると仮定して、現在の DataListItem
にバインドされている実際の ProductsRow
インスタンスにアクセスします。 DataListItem
の DataItem
プロパティには 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
Dim ProductNameLabel As Label = CType(e.Item.FindControl("ProductNameLabel"), Label)
Dim UnitPriceLabel As Label = CType(e.Item.FindControl("UnitPriceLabel"), Label)
' Next, set their CssClass properties
If ProductNameLabel IsNot Nothing Then
ProductNameLabel.CssClass = "AffordablePriceEmphasis"
End If
If UnitPriceLabel IsNot Nothing Then
UnitPriceLabel.CssClass = "AffordablePriceEmphasis"
End If
ItemDataBound
イベント ハンドラーが完了したら、ブラウザーで Formatting.aspx
ページに再度アクセスします。 図 2 に示すように、価格が 20.00 ドル未満の製品は、名前と価格の両方が強調表示されています。
図 2: 20.00 ドル未満の製品が強調表示されています (クリックするとフルサイズの画像が表示されます)
Note
DataList は HTML <table>
としてレンダリングされるため、その DataListItem
インスタンスには、項目全体に特定のスタイルを適用するように設定できるスタイル関連のプロパティがあります。 たとえば、価格が 20.00 ドル未満の項目 "全体" を黄色で強調表示したい場合は、Labels を参照するコードを置き換えて、その CssClass
プロパティをコード行 e.Item.CssClass = "AffordablePriceEmphasis"
で設定できます (図 3 を参照)。
ただし、Repeater コントロールを構成する RepeaterItem
は、そのようなスタイル レベルのプロパティを提供しません。 そのため、Repeater にカスタム書式を適用するには、図 2 のように、Repeater のテンプレート内の Web コントロールにスタイル プロパティを適用する必要があります。
図 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 は、これらの書式設定ルールが適用された製品リストのスクリーン ショットを示しています。
図 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 Function DisplayProductNameAndDiscontinuedStatus _
(productName As String, discontinued As Boolean) As String
' Return just the productName if discontinued is false
If Not discontinued Then
Return productName
Else
' otherwise, return the productName appended with the text "[DISCONTINUED]"
Return String.Concat(productName, " [DISCONTINUED]")
End If
End Function
Protected Function DisplayPrice(product As Northwind.ProductsRow) As String
' If price is less than $20.00, return the price, highlighted
If Not product.IsUnitPriceNull() AndAlso product.UnitPrice < 20 Then
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>"
End If
End Function
DisplayProductNameAndDiscontinuedStatus
メソッドは、productName
および discontinued
データ フィールドの値をスカラー値として受け入れるのに対し、DisplayPrice
メソッドは (unitPrice
スカラー値ではなく) ProductsRow
インスタンスを受け入れることに注意してください。 どちらの方法でも機能します。ただし、書式設定関数がデータベースの NULL
値を含む可能性のあるスカラー値 (UnitPrice
など) を扱う場合 (ProductName
または Discontinued
はどちらも NULL
値を許可しない)、これらのスカラー入力の処理には特別な注意が必要です。
特に、入力パラメーターは Object
型である必要があります。入力値は、想定されるデータ型ではなく DBNull
インスタンスである可能性があるためです。 さらに、受信値がデータベースの NULL
値であるかどうかを確認するためにチェックを行う必要があります。 つまり、DisplayPrice
メソッドで価格をスカラー値として受け入れる必要がある場合は、次のコードを使用する必要があります。
Protected Function DisplayPrice(ByVal unitPrice As Object) As String
' If price is less than $20.00, return the price, highlighted
If Not Convert.IsDBNull(unitPrice) AndAlso CType(unitPrice, Decimal) < 20 Then
Return String.Concat("<span class="AffordablePriceEmphasis">", _
CType(unitPrice, Decimal).ToString("C"), "</span>")
Else
' Otherwise return the text, "Please call for a price quote"
Return "<span>Please call for a price quote</span>"
End If
End Function
unitPrice
入力パラメーターは Object
型であり、unitPrice
が DBNull
であるかどうかを確認するために条件ステートメントが変更されていることに注意してください。 さらに、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")
構文を使用して製品名と廃止された値を渡す必要があります。 Eval
は Object
型の値を返しますが、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" というテキストに置き換えらています。
図 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行をドロップしてください。