ObjectDataSource でデータを表示する (C#)
このチュートリアルでは、ObjectDataSource コントロールについて説明します。このコントロールを使用すると、前のチュートリアルで作成した BLL から取得したデータのバインドを、コードを記述することなく実現できます。
はじめに
ここでは、アプリケーション アーキテクチャと Web サイトのページ レイアウトを完成させた後、さまざまな種類の一般的なデータ関連タスクやレポート関連タスクを実行する方法について見ていきます。 これまでのチュートリアルでは、DAL と BLL のデータを ASP.NET ページ内のデータ Web コントロールにプログラムでバインドする方法を説明しました。 データ Web コントロールの DataSource
プロパティを表示するデータに割り当て、コントロールの DataBind()
メソッドを呼び出すその構文は、ASP.NET 1.x アプリケーションで使用されてきたパターンであり、2.0 アプリケーションでも引き続き使用できます。 ただし、ASP.NET 2.0 の新しいデータ ソース コントロールには、宣言的な方法でデータを扱える機能があります。 新しいコントロールを使用すると、前のチュートリアルで作成した BLL から取得したデータのバインドを、コードを記述することなく実現できます。
ASP.NET 2.0 には、組み込みのデータ ソース コントロールとして SqlDataSource、AccessDataSource、ObjectDataSource、XmlDataSource、SiteMapDataSource の 5 つが付属していますが、必要に応じて独自のカスタム データ ソース コントロールを作成することもできます。 このチュートリアルのアプリケーションの場合、既にアーキテクチャを開発したので、BLL クラスに対して ObjectDataSource を使用することにします。
図 1: ASP.NET 2.0 に含まれている 5 つの組み込みデータ ソース コントロール
ObjectDataSource は、何らかの別のオブジェクトを操作するためのプロキシとして機能します。 ObjectDataSource を構成するには、対象となる基盤オブジェクトを指定し、基盤オブジェクトの各種メソッドと ObjectDataSource の Select
、Insert
、Update
、Delete
メソッドとのマッピングを指定します。 基盤オブジェクトを指定し、メソッドを ObjectDataSource にマッピングすると、その ObjectDataSource はデータ Web コントロールにバインド可能になります。 ASP.NET には、GridView、DetailsView、RadioButtonList、DropDownList など多数のデータ Web コントロールが付属しています。 データ Web コントロールは、ページのライフサイクルに従い、バインドされているデータへのアクセスが必要になると ObjectDataSource の Select
メソッドを呼び出すことがあります。また、挿入、更新、または削除をサポートするデータ Web コントロールの場合は、ObjectDataSource の Insert
、Update
、または Delete
メソッドも呼び出すことがあります。 それらの呼び出しは、以下の図に示すように、ObjectDataSource によって基盤オブジェクトの適切なメソッドへとルーティングされます。
図 2: ObjectDataSource はプロキシとして機能する (クリックするとフルサイズの画像が表示されます)
ObjectDataSource を使うとデータの挿入、更新、削除を行うメソッドを呼び出すことができますが、ここではデータを返す操作のみに注目します。ObjectDataSource とデータを変更するデータ Web コントロールの使用については、後のチュートリアルで調べます。
ステップ 1: ObjectDataSource コントロールを追加して構成する
まず、BasicReporting
フォルダー内の SimpleDisplay.aspx
ページを開き、デザイン ビューに切り替えて、ツールボックスから、ObjectDataSource コントロールをページのデザイン サーフェイスにドラッグします。 ObjectDataSource は、マークアップを生成しないコントロールであるため、デザイン サーフェイス上では灰色のボックスとして表示されます。このコントロールは、指定されたオブジェクトのメソッドを呼び出してデータ アクセスのみを行います。 ObjectDataSource から返されるデータは、GridView、DetailsView、FormView などのデータ Web コントロールを使用して表示できます。
Note
または、最初にデータ Web コントロールをページに追加し、このコントロールのスマート タグで、ドロップダウン リストから [<新しいデータ ソース>] オプションを選択することもできます。
ObjectDataSource の基になるオブジェクトを指定し、そのオブジェクトのメソッドと ObjectDataSource のメソッドとのマッピングを指定するには、ObjectDataSource のスマート タグで、[データ ソースの構成] リンクをクリックします。
図 3: スマート タグの [データ ソースの構成] リンクをクリックする (クリックするとフルサイズの画像が表示されます)
データ ソースの構成ウィザードが表示されます。 まず、ObjectDataSource での操作対象となるオブジェクトを指定する必要があります。 [データ コンポーネントのみを表示] チェック ボックスをオンにすると、この画面のドロップダウン リストには、DataObject
属性で装飾されたオブジェクトのみが表示されるようになります。 現在、このリストには、型指定された DataSet の TableAdapter と、前のチュートリアルで作成した BLL クラスが含まれています。 ビジネス ロジック層のクラスに DataObject
属性を追加するのを忘れた場合、それらのクラスは表示されません。 その場合は [データ コンポーネントのみを表示] チェック ボックスをオフにすると、すべてのオブジェクトが (BLL クラスだけでなく、型指定された DataSet の他のクラス、DataTable、DataRow なども含め) 表示されます。
この最初の画面で、ドロップダウン リストから ProductsBLL
クラスを選択し、[次へ] をクリックします。
図 4: ObjectDataSource コントロールで使用するオブジェクトを指定する (クリックするとフルサイズの画像が表示されます)
ウィザードの次の画面では、ObjectDataSource から呼び出すメソッドの選択を求められます。 ドロップダウンに、前の画面で選択したオブジェクトのデータを返すメソッドの一覧が表示されます。 この例では GetProductByProductID
、GetProducts
、GetProductsByCategoryID
、GetProductsBySupplierID
が表示されます。 ドロップダウン リストから GetProducts
メソッドを選択し、[完了] をクリックします (前のチュートリアルで示したとおり ProductBLL
のメソッドに DataObjectMethodAttribute
を付加した場合、このオプションが既定で選択されます)。
図 5: [SELECT] タブで、データを返すメソッドを選択する (クリックするとフルサイズの画像が表示されます)
ObjectDataSource を手動で構成する
ObjectDataSource データ ソースの構成ウィザードでは、使用するオブジェクトの指定と、そのオブジェクトに対して呼び出すメソッドの関連付けを手早く実行できます。 一方、ObjectDataSource のプロパティを、プロパティ ウィンドウで構成するか、宣言型マークアップで直接構成することもできます。 その方法は、TypeName
プロパティに、使用する基になるオブジェクトの型を設定し、SelectMethod
プロパティに、データ取得時に呼び出すメソッドを設定するだけです。
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
SelectMethod="GetProducts" TypeName="ProductsBLL">
</asp:ObjectDataSource>
データ ソースの構成ウィザードを使用するときも、ウィザードに表示されるのは開発者によって作成されたクラスのみであるため、場合によっては ObjectDataSource の手動構成が必要になります。 ObjectDataSource を .NET Framework のクラスにバインドする場合 (例: Membership クラスでユーザー アカウント情報にアクセスする場合や、Directory クラスでファイル システム情報を扱う場合) には、ObjectDataSource のプロパティを手動で設定する必要があります。
ステップ 2: データ Web コントロールを追加して ObjectDataSource にバインドする
ObjectDataSource をページに追加し、構成した後は、ObjectDataSource の Select
メソッドから返されるデータを表示するためのデータ Web コントロールをページに追加します。 どのデータ Web コントロールも ObjectDataSource にバインド可能ですが、ここでは、GridView、DetailsView、FormView に ObjectDataSource のデータを表示する方法を見てみましょう。
GridView を ObjectDataSource にバインドする
ツールボックスから、GridView コントロールを SimpleDisplay.aspx
のデザイン サーフェイスに追加します。 GridView のスマート タグで、ステップ 1 で追加した ObjectDataSource コントロールを選択します。 これにより、ObjectDataSource の Select
メソッドから返されるデータの各プロパティ (つまり、Products DataTable によって定義されたプロパティ) について、GridView 内に BoundField が自動的に作成されます。
図 6: GridView がページに追加され、ObjectDataSource にバインドされる (クリックするとフルサイズの画像が表示されます)
その後、スマート タグの [列の編集] オプションをクリックすると、GridView の BoundField をカスタマイズ、再配置、または削除できます。
図 7: [列の編集] ダイアログ ボックスを使用して GridView の BoundField を管理する (クリックするとフルサイズの画像が表示されます)
ここで、GridView の BoundField を変更し、ProductID
、SupplierID
、CategoryID
、QuantityPerUnit
、UnitsInStock
、UnitsOnOrder
、ReorderLevel
BoundField を削除します。 これを行うには、目的の BoundField を単に左下のリストから選択し、削除ボタン (赤い X) をクリックします。 次に、CategoryName
および SupplierName
BoundField を選択して上矢印をクリックすることで、これらを UnitPrice
BoundField よりも上に再配置します。 残っている BoundField について、HeaderText
プロパティをそれぞれ Products
、Category
、Supplier
、Price
に設定します。 次に、Price
BoundField の HtmlEncode
プロパティを False に、DataFormatString
プロパティを {0:c}
に設定して、この BoundField に通貨の書式設定を適用します。 最後に、ItemStyle
/HorizontalAlign
プロパティで、Price
の水平方向の配置を右揃えに、Discontinued
チェック ボックスを中央揃えにします。
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ObjectDataSource1"
EnableViewState="False">
<Columns>
<asp:BoundField DataField="ProductName"
HeaderText="Product" SortExpression="ProductName" />
<asp:BoundField DataField="CategoryName"
HeaderText="Category" ReadOnly="True"
SortExpression="CategoryName" />
<asp:BoundField DataField="SupplierName"
HeaderText="Supplier" ReadOnly="True"
SortExpression="SupplierName" />
<asp:BoundField DataField="UnitPrice"
DataFormatString="{0:c}" HeaderText="Price"
HtmlEncode="False" SortExpression="UnitPrice">
<ItemStyle HorizontalAlign="Right" />
</asp:BoundField>
<asp:CheckBoxField DataField="Discontinued"
HeaderText="Discontinued" SortExpression="Discontinued">
<ItemStyle HorizontalAlign="Center" />
</asp:CheckBoxField>
</Columns>
</asp:GridView>
図 8: GridView の BoundField がカスタマイズされている (クリックするとフルサイズの画像が表示されます)
テーマを使用して外観を統一する
これらのチュートリアルでは、可能な限りコントロール レベルのスタイル設定を削除し、外部ファイルで定義されたカスケード スタイル シートを使用します。 Styles.css
ファイルには、これらのチュートリアルで使用すデータ Web コントロールの外観を指定するための CSS クラス DataWebControlStyle
、HeaderStyle
、RowStyle
、AlternatingRowStyle
が含まれています。 これを実現するには、GridView の CssClass
プロパティを DataWebControlStyle
に設定し、HeaderStyle
、RowStyle
、AlternatingRowStyle
各プロパティの CssClass
プロパティをそれぞれ設定します。
これらの CssClass
プロパティを Web コントロールで設定する場合は、チュートリアルに追加するすべてのデータ Web コントロールに対し、明示的にこれらのプロパティ値を設定する必要があります。 それよりも管理しやすいアプローチとして、テーマを使用して GridView、DetailsView、FormView コントロールの既定の CSS 関連プロパティを定義する方法があります。 テーマとは、コントロール レベルのプロパティ設定群、画像群、CSS クラス群をまとめたコレクションであり、サイト全体のページに同じテーマを適用することで外観を統一できます。
このチュートリアルで使用するテーマは、画像や CSS ファイルを含まず (Web アプリケーションのルート フォルダーに定義されている Styles.css
スタイルシートは変更しません)、スキンを 2 つ含むものとします。 スキンとは、Web コントロールの既定のプロパティを定義するファイルです。 ここでは、GridView コントロールと DetailsView コントロール用に、既定の CssClass
関連プロパティを示すスキン ファイルを使用します。
まず、ソリューション エクスプローラーでプロジェクト名を右クリックし、[新しい項目の追加] を選択して、GridView.skin
という新しいスキン ファイルをプロジェクトに追加します。
図 9: GridView.skin
というスキン ファイルを追加する (クリックするとフルサイズの画像が表示されます)
スキン ファイルはテーマ内に置く必要があり、テーマは App_Themes
フォルダーに格納されます。 最初のスキンを追加する際は、このフォルダーがまだ存在せず、フォルダーの作成を提案するメッセージが Visual Studio に表示されます。 [はい] をクリックして App_Theme
フォルダーを作成し、新しい GridView.skin
ファイルをここに配置します。
図 10: Visual Studio で App_Theme
フォルダーを作成する (クリックするとフルサイズの画像が表示されます)
これにより、App_Themes
フォルダー内に GridView という新しいテーマが作成され、その中に GridView.skin
というスキン ファイルが作成されます。
図 11: GridView テーマが App_Theme
フォルダーに追加されている
この GridView というテーマ名を DataWebControls に変更します (App_Theme
フォルダー内の GridView フォルダーを右クリックし、[名前の変更] を選択します)。 次に、以下のマークアップを GridView.skin
ファイルに入力します。
<asp:GridView runat="server" CssClass="DataWebControlStyle">
<AlternatingRowStyle CssClass="AlternatingRowStyle" />
<RowStyle CssClass="RowStyle" />
<HeaderStyle CssClass="HeaderStyle" />
</asp:GridView>
これは、DataWebControls テーマを使用するすべてのページ内にあるすべての GridView の CssClass
関連プロパティに適用される既定プロパティの定義です。 同じように、DetailsView (この後すぐに使用するデータ Web コントロール) 用のスキンもここで追加しましょう。 DataWebControls テーマに DetailsView.skin
という新しいスキンを追加し、以下のマークアップを追加します。
<asp:DetailsView runat="server" CssClass="DataWebControlStyle">
<AlternatingRowStyle CssClass="AlternatingRowStyle" />
<RowStyle CssClass="RowStyle" />
<FieldHeaderStyle CssClass="HeaderStyle" />
</asp:DetailsView>
テーマを定義した後は、最後のステップとして、そのテーマを ASP.NET ページに適用します。 テーマは個別のページに適用することも、Web サイト内のすべてのページに適用することもできます。 このテーマは Web サイト内のすべてのページに適用することにします。 適用するには、Web.config
の <system.web>
セクションに以下のマークアップを追加します。
<pages styleSheetTheme="DataWebControls" />
これですべて完了です。 styleSheetTheme
の設定は、テーマで指定されているプロパティが、コントロール レベルで指定されているプロパティをオーバーライドしては "ならない" ことを示します。 テーマでの設定をコントロールの設定より優先させる場合は、styleSheetTheme
ではなく theme
属性を使用します。残念ながら、theme
属性で指定されているテーマの設定は、Visual Studio のデザイン ビューには表示されません。 テーマとスキンの詳細については、ASP.NET のテーマとスキンの概要、およびテーマによるサーバー側でのスタイル指定に関するドキュメントを参照してください。テーマを使用するためのページ構成方法の詳細については、ASP.NET テーマを適用する方法に関するドキュメントを参照してください。
図 12: GridView に製品の名前、カテゴリ、サプライヤー、価格、製造中止情報が表示される (クリックするとフルサイズの画像が表示されます)
レコード 1 件ずつを DetailsView に表示する
GridView の場合、バインド先のデータ ソース コントロールから返される個々のレコードは個々の行として表示されます。 一方、1 レコードを表示する場合や、一度に 1 レコードだけ表示する場合もあります。 DetailsView はそのような機能を提供するコントロールであり、バインドされた個々の列またはプロパティを 2 列 1 行の HTML <table>
としてレンダリングします。 DetailsView は、GridView 内のレコード 1 件を 90 度回転させて表示するようなものと考えることができます。
まず、SimpleDisplay.aspx
内にある GridView の "上" に DetailsView コントロールを追加します。 次に、GridView のバインド先と同じ ObjectDataSource コントロールにバインドします。 GridView と同様に、ObjectDataSource の Select
メソッドから返されるオブジェクト内の各プロパティについて、DetailsView 内に BoundField が追加されます。 唯一の違いは、BoundField のレイアウトが、DetailsView の場合は垂直方向でなく水平方向になっていることです。
図 13: DetailsView をページに追加し、ObjectDataSource にバインドする (クリックするとフルサイズの画像が表示されます)
GridView の場合と同じように DetailsView でも、BoundField を調整することで、ObjectDataSource から返されるデータの表示を高度にカスタマイズできます。 図 14 は、DetailsView の外観を GridView の例に似せるように BoundField と CssClass
プロパティを構成した結果を示しています。
図 14: DetailsView に 1 レコードが表示される (クリックするとフルサイズの画像が表示されます)
DetailsView に表示されるのは、データ ソースから返された最初のレコードのみです。 ユーザーが一度に 1 件ずつすべてのレコードを順番に表示できるようにするには、DetailsView のページングを有効にする必要があります。 これを行うには、Visual Studio に戻り、DetailsView のスマート タグで、[ページングを有効にする] チェック ボックスをオンにします。
図 15: DetailsView コントロールのページングを有効にする (クリックするとフルサイズの画像が表示されます)
図 16: ページングを有効にした DetailsView では、ユーザーは任意の製品を表示できる (クリックするとフルサイズの画像が表示されます)
ページングの詳細については、今後のチュートリアルで取り上げます。
より柔軟なレイアウトで一度に 1 件ずつのレコードを表示する
DetailsView では、ObjectDataSource から返された個別レコードの表示方法がかなり限定されています。 より柔軟なデータ表示方法が必要になることがあります。 たとえば、製品名、カテゴリ、サプライヤー、価格、販売終了の情報を単に別々の行に表示するのではなく、<h4>
見出しに製品名と価格を表示し、その下に、カテゴリとサプライヤーの情報を小さいフォント サイズで表示するといったレイアウトのニーズがあります。 また、プロパティ名 (Product、Category など) を値の横に表示することが望ましくない場合もあります。
FormView は、そのようなレベルのカスタマイズ機能を提供するコントロールです。 GridView や DetailsView がフィールドを使用するのに対し、FormView では、テンプレートを使用して Web コントロール、静的 HTML、データ バインディング構文を組み合わせることができます。 ASP.NET 1.x の Repeater コントロールを使い慣れた開発者向けに説明するなら、FormView とは、1 件のレコードを表示する Repeater のようなものです。
FormView コントロールを、SimpleDisplay.aspx
ページのデザイン サーフェイスに追加します。 最初、FormView は灰色のブロックとして表示されます。これは、少なくともコントロールの ItemTemplate
を指定する必要があることを示しています。
図 17: FormView は ItemTemplate
を含む必要がある (クリックするとフルサイズの画像が表示されます)
FormView のスマート タグを使用すると、FormView をデータ ソース コントロールに直接バインドでき、既定の ItemTemplate
が自動的に作成されます (ObjectDataSource コントロールの InsertMethod
と UpdateMethod
プロパティが設定されている場合は、EditItemTemplate
と InsertItemTemplate
も)。 しかし、ここに示す例では、データから FormView へのバインドと ItemTemplate
の指定を手動で行います。 まず、FormView の DataSourceID
プロパティを、ObjectDataSource コントロール ObjectDataSource1
の ID
に設定します。 次に、ItemTemplate
を作成して、製品の名前と価格は <h4>
要素に表示、カテゴリと配送業者の名前はその下に小さいフォント サイズで表示するようにします。
<asp:FormView ID="FormView1" runat="server"
DataSourceID="ObjectDataSource1" EnableViewState="False">
<ItemTemplate>
<h4><%# Eval("ProductName") %>
(<%# Eval("UnitPrice", "{0:c}") %>)</h4>
Category: <%# Eval("CategoryName") %>;
Supplier: <%# Eval("SupplierName") %>
</ItemTemplate>
</asp:FormView>
図 18: 最初の製品 (Chai) がカスタム形式で表示されている (クリックするとフルサイズの画像が表示されます)
<%# Eval(propertyName) %>
はデータ バインディング構文です。 Eval
メソッドは、FormView コントロールにバインドされている現在のオブジェクトについて、指定されたプロパティの値を返します。 データ バインディングの詳細については、Alex Homer の記事「ASP.NET 2.0 の簡略版および拡張版データ バインディング構文」を参照してください。
DetailsView の場合と同じく、FormView では、ObjectDataSource から返された最初のレコードのみが表示されます。 FormView のページングを有効にすると、ユーザーが製品情報を一度に 1 つずつ順番に表示できるようになります。
まとめ
ASP.NET 2.0 の ObjectDataSource コントロールを使用すると、コードを記述することなく、ビジネス ロジック レイヤーのデータにアクセスして表示する機能を実現できます。 ObjectDataSource は、指定されたクラスの指定されたメソッドを呼び出し、結果を返します。 それらの結果は、ObjectDataSource にバインドしたデータ Web コントロールを使用して表示できます。 このチュートリアルでは、GridView、DetailsView、FormView コントロールを ObjectDataSource にバインドする方法について説明しました。
ここまでは、ObjectDataSource を使用してパラメーターなしのメソッドを呼び出す方法だけを説明してきました。では、入力パラメーターを必要とするメソッド (例: ProductBLL
クラスの GetProductsByCategoryID(categoryID)
) を呼び出す場合はどうすればよいでしょうか。 1 つまたは複数のパラメーターを受け取るメソッドを呼び出すには、それらのパラメーターの値を指定するように ObjectDataSource を構成する必要があります。 その実現方法については、次のチュートリアルで説明します。
プログラミングに満足!
もっと読む
この記事で説明したトピックの詳細については、次のリソースを参照してください。
- 独自のデータ ソース コントロールの作成
- ASP.NET 2.0 の GridView の例
- ASP.NET 2.0 のテーマ
- テーマによるサーバー側でのスタイル指定
- 方法: プログラムによって ASP.NET テーマを適用する
著者について
7 冊の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジに取り組んでいます。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズは24時間で2.0 ASP.NET 自分自身を教えています。 にアクセスするか、ブログを使用して にアクセスmitchell@4GuysFromRolla.comできます。これは でhttp://ScottOnWriting.NET見つけることができます。
特別な感謝
このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は Hilton Giesenow です。 今後の MSDN の記事を確認することに関心がありますか? ご希望の場合は、mitchell@4GuysFromRolla.com までメッセージをお送りください。