Share via


マスター レコードの箇条書きと詳細 DataList を使用してマスター/詳細を表示する (VB)

作成者: Scott Mitchell

PDF のダウンロード

このチュートリアルでは、前のチュートリアルの 2 ページのマスター/詳細レポートを 1 つのページに圧縮し、画面の左側にカテゴリ名の箇条書きと、画面の右側に選択したカテゴリの製品を示します。

はじめに

前の チュートリアル では、マスター/詳細レポートを 2 ページに分ける方法について説明しました。 マスター ページでは、Repeater コントロールを使用して、カテゴリの箇条書きをレンダリングしました。 各カテゴリ名はハイパーリンクであり、クリックするとユーザーが詳細ページに移動し、2 列の DataList に選択したカテゴリに属する製品が表示されます。

このチュートリアルでは、2 ページのチュートリアルを 1 つのページに圧縮し、画面の左側にカテゴリ名の箇条書きの一覧が表示され、各カテゴリ名が LinkButton としてレンダリングされます。 カテゴリ名 LinkButtons のいずれかをクリックすると、ポストバックが行われ、選択したカテゴリの製品が画面の右側にある 2 列の DataList にバインドされます。 左側の Repeater には、各カテゴリの名前の表示に加えて、特定のカテゴリの合計製品数が表示されます (図 1 を参照)。

[カテゴリ名] と [製品の合計数] が左側に表示されます

図 1: カテゴリの名前と製品の合計数が左側に表示されます (フルサイズの画像を表示する をクリックします)

手順 1: 画面の左側にリピータを表示する

このチュートリアルでは、選択したカテゴリの製品の左側にカテゴリの箇条書きを表示する必要があります。 Web ページ内のコンテンツは、標準の HTML 要素の段落タグ、改行しないスペース、など、 <table> カスケード スタイルシート (CSS) 手法を使用して配置できます。 ここまでのすべてのチュートリアルでは、配置に CSS 手法を使用してきました。 マスター ページとサイト ナビゲーションのチュートリアルのマスター ページでナビゲーション ユーザー インターフェイスを構築したときに、ナビゲーション リストとメインコンテンツの正確なピクセル オフセットを示す絶対配置を使用しました。 または、CSS を使用して、 浮動を通じて 1 つの要素を別の要素の右または左に配置することもできます。 DataList の左側に Repeater を浮動させることで、選択したカテゴリの製品の左側に項目の箇条書きを表示できます

CategoriesAndProducts.aspxフォルダーからページをDataListRepeaterFiltering開き、ページに Repeater と DataList を追加します。 Repeater s ID を に Categories 設定し、DataList s を に CategoryProducts設定します。 [ソース] ビューに移動し、Repeater コントロールと DataList コントロールを独自 <div> の要素内に配置します。 つまり、最初に要素内で Repeater を <div> 囲み、次に、Repeater の直後の独自 <div> の要素で DataList を囲みます。 この時点のマークアップは、次のようになります。

<div>
    <asp:Repeater ID="Categories" runat="server">
    </asp:Repeater>
</div>
<div>
    <asp:DataList ID="CategoryProducts" runat="server">
    </asp:DataList>
</div>

DataList の左側に Repeater をフローティングするには、次のように CSS スタイル属性を float 使用する必要があります。

<div>
    Repeater
</div>
<div>
    DataList
</div>

float: left; 、最初 <div> の要素を 2 番目の要素の左側に浮動します。 と padding-right の設定はwidth、最初<div>の s と、要素のwidthコンテンツとその右余白の間に<div>追加されるパディングの量を示します。 CSS のフローティング要素の詳細については、Floatutorial をチェックします。

最初<p>の要素の s style 属性を使用してスタイル設定を直接指定するのではなく、 という名前FloatLeftの新しい CSS クラスStyles.cssを作成してみましょう。

.FloatLeft
{
    float: left;
    width: 33%;
    padding-right: 10px;
}

その後、 を に<div><div class="FloatLeft">置き換えることができます。

CSS クラスを追加し、ページでマークアップをCategoriesAndProducts.aspx構成したら、Designerに移動します。 DataList の左側に Repeater が浮動しているはずです (ただし、データ ソースまたはテンプレートをまだ構成していないため、現時点ではどちらも灰色のボックスとして表示されます)。

Repeater は DataList の左側に浮動します

図 2: Repeater は DataList の左側に浮動します (フルサイズの画像を表示する場合は、ここをクリックします)

手順 2: 各カテゴリの製品数を決定する

Repeater と DataList の周囲のマークアップが完了したら、カテゴリ データを Repeater コントロールにバインドする準備ができました。 ただし、図 1 のカテゴリの箇条書きが示すように、各カテゴリの名前に加えて、カテゴリに関連付けられている製品の数も表示する必要があります。 この情報にアクセスするには、次のいずれかを行います。

  • この情報は、ASP.NET ページの分離コード クラスから確認します。 特定categoryIDの場合、クラスの GetProductsByCategoryID(categoryID) メソッドを呼び出すことによって、関連付けられている製品の数をProductsBLL決定できます。 このメソッドは、 ProductsDataTable プロパティが Count 存在する の数 ProductsRow を示す オブジェクトを返します。これは、指定された categoryIDの製品の数です。 Repeater のイベント ハンドラーをItemDataBound作成して、Repeater にバインドされている各カテゴリについて、クラスの メソッドGetProductsByCategoryID(categoryID)ProductsBLL呼び出し、その数を出力に含めることができます。
  • 型指定された DataSet の を CategoriesDataTable 更新して、列を NumberOfProducts 含めます。 次に、 の メソッドをGetCategories()更新してこの情報を含めます。または、そのままにしてGetCategories()、 というGetCategoriesAndNumberOfProducts()名前の新しいCategoriesDataTableメソッドを作成CategoriesDataTableすることもできます。

これらの手法の両方を調べてみましょう。 最初のアプローチは、データ アクセス層を更新する必要がないため、実装が簡単です。ただし、データベースとの通信を増やす必要があります。 イベント ハンドラーで クラス s GetProductsByCategoryID(categoryID) メソッドをProductsBLL呼び出すと、Repeater にItemDataBound表示されるカテゴリごとにデータベース呼び出しが追加されます。 この手法では、 N + 1 データベース呼び出しがあり、 N は Repeater に表示されるカテゴリの数です。 2 番目の方法では、製品数がクラスの GetCategories() (または GetCategoriesAndNumberOfProducts()) メソッドからCategoriesBLL各カテゴリに関する情報と共に返されるため、データベースに 1 回だけトリップします。

ItemDataBound イベント ハンドラーでの製品数の決定

Repeater のイベント ハンドラーで各カテゴリの製品の数を決定する場合、既存の ItemDataBound データ アクセス層を変更する必要はありません。 すべての変更は、ページ内で CategoriesAndProducts.aspx 直接行うことができます。 まず、Repeater のスマート タグを使用して という名前 CategoriesDataSource の新しい ObjectDataSource を追加します。 次にCategoriesDataSource、ObjectDataSource を構成して、クラスの GetCategories() メソッドからデータをCategoriesBLL取得します。

CategoriesBLL クラス s GetCategories() メソッドを使用するように ObjectDataSource を構成する

図 3: クラス s GetCategories() メソッドを使用CategoriesBLLするように ObjectDataSource を構成する (フルサイズの画像を表示する 場合はクリックします)

Repeater の各項目は Categories クリック可能である必要があり、クリックすると、選択したカテゴリの CategoryProducts 製品が DataList に表示されます。 これは、前のチュートリアルで見たのと同じように、各カテゴリをハイパーリンクにして、この同じページ (CategoriesAndProducts.aspx) にリンクし直しますが、クエリ文字列を渡 CategoryID すことで実現できます。 この方法の利点は、特定のカテゴリの製品を表示するページを検索エンジンでブックマークおよびインデックス付けできることです。

または、各カテゴリを LinkButton にすることもできます。これは、このチュートリアルで使用するアプローチです。 LinkButton はユーザーのブラウザーでハイパーリンクとしてレンダリングされますが、クリックするとポストバックが発生します。ポストバック時に、選択したカテゴリに属する製品を表示するには、DataList の ObjectDataSource を更新する必要があります。 このチュートリアルでは、LinkButton を使用するよりもハイパーリンクを使用する方が理にかなっています。ただし、LinkButton を使用する方が有利なシナリオは他にもあります。 ハイパーリンクアプローチはこの例に最適ですが、代わりに LinkButton を使用して調べてみましょう。 ご覧のように、LinkButton を使用すると、ハイパーリンクで発生しないいくつかの課題が発生します。 したがって、このチュートリアルで LinkButton を使用すると、これらの課題が強調され、ハイパーリンクではなく LinkButton を使用するシナリオの解決策を提供するのに役立ちます。

注意

LinkButton の代わりに HyperLink コントロールまたは <a> 要素を使用して、このチュートリアルを繰り返することをお勧めします。

次のマークアップは、Repeater と ObjectDataSource の宣言構文を示しています。 Repeater のテンプレートでは、各項目を含む箇条書きが LinkButton としてレンダリングされることに注意してください。

<asp:Repeater ID="Categories" runat="server" DataSourceID="CategoriesDataSource">
    <HeaderTemplate>
        <ul>
    </HeaderTemplate>
    <ItemTemplate>
        <li><asp:LinkButton runat="server" ID="ViewCategory"></asp:LinkButton></li>
    </ItemTemplate>
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>

注意

このチュートリアルでは、Repeater のビューステートを有効にする必要があります (Repeater の宣言構文からの の EnableViewState="False" 省略に注意してください)。 手順 3 では、DataList の ObjectDataSource SelectParameters コレクションを更新する Repeater イベントItemCommandのイベント ハンドラーを作成します。 ただし、ビューステートが無効になっている場合、Repeater の ItemCommandは起動しません。

プロパティ値が の IDViewCategory LinkButton には、その Text プロパティが設定されていません。 カテゴリ名を表示するだけの場合は、次のように、データバインド構文を使用して Text プロパティを宣言的に設定します。

<asp:LinkButton runat="server" ID="ViewCategory"
    Text='<%# Eval("CategoryName") %>' />

ただし、カテゴリの名前 、そのカテゴリに属する製品の数の両方を表示する必要があります。 この情報は、次のコードに示すように、 クラスの ItemDataBound メソッドをProductBLL呼び出し、結果の ProductsDataTableで返されるレコードの数を決定することで、Repeater のGetCategoriesByProductID(categoryID)イベント ハンドラーから取得できます。

Protected Sub Categories_ItemDataBound(sender As Object, e As RepeaterItemEventArgs)
    ' Make sure we're working with a data item...
    If e.Item.ItemType = ListItemType.Item OrElse _
        e.Item.ItemType = ListItemType.AlternatingItem Then
        ' Reference the CategoriesRow instance bound to this RepeaterItem
        Dim category As Northwind.CategoriesRow = _
            CType(CType(e.Item.DataItem, System.Data.DataRowView).Row, _
                Northwind.CategoriesRow)
        ' Determine how many products are in this category
        Dim productsAPI As New NorthwindTableAdapters.ProductsTableAdapter
        Dim productCount As Integer = _
            productsAPI.GetProductsByCategoryID(category.CategoryID).Count
        ' Reference the ViewCategory LinkButton and set its Text property
        Dim ViewCategory As LinkButton = _
            CType(e.Item.FindControl("ViewCategory"), LinkButton)
        ViewCategory.Text = _
            String.Format("{0} ({1:N0})", category.CategoryName, productCount)
    End If
End Sub

まず、データ項目 (ItemTypeItemが または AlternatingItemである項目) を使用していることを確認してから、現在RepeaterItemCategoriesRow にバインドされたインスタンスを参照します。 次に、 クラスのインスタンス ProductsBLL を作成し、その GetCategoriesByProductID(categoryID) メソッドを呼び出し、 プロパティを使用して返されるレコードの数を決定することで、このカテゴリの製品の数を Count 決定します。 最後に、ItemTemplate の LinkButton は参照であり、 ViewCategory その Text プロパティは CategoryName (NumberOfProductsInCategory) に設定されます。 ここで、NumberOfProductsInCategory は小数点以下 0 の数値として書式設定されます。

注意

または、カテゴリと値を受け入れ、カテゴリ内の製品の数と連結された を返CategoryName書式設定関数を ASP.NET ページのCategoryNameCategoryID分離コード クラスに追加することもできます (メソッドの呼び出しGetCategoriesByProductID(categoryID)によって決定されます)。 このような書式設定関数の結果は、イベント ハンドラーの必要性を置き換える LinkButton の Text プロパティに宣言的に ItemDataBound 割り当てることができます。 書式設定関数の使用の詳細については、「 GridView コントロールでの TemplateFields の使用 」または 「DataList と Repeater Based On Data の書式設定」のチュートリアルを参照してください。

このイベント ハンドラーを追加した後、ブラウザーを使用してページをテストします。 各カテゴリが箇条書きに表示され、カテゴリの名前とカテゴリに関連付けられている製品の数が表示されることに注意してください (図 4 を参照)。

各カテゴリの名前と製品の数が表示されます

図 4: 各カテゴリの名前と製品の数が表示されます (フルサイズの画像を表示する をクリックします)

CategoriesTableAdapterCategoriesDataTable更新して、各カテゴリの製品数を含める

Repeater にバインドされている各カテゴリの製品の数を決定するのではなく、データ アクセス層の と CategoriesTableAdapter を調整してこの情報をCategoriesDataTableネイティブに含めることで、このプロセスを効率化できます。 これを実現するには、関連付けられている製品の数を保持するために、 に CategoriesDataTable 新しい列を追加する必要があります。 DataTable に新しい列を追加するには、型指定された DataSet (App_Code\DAL\Northwind.xsd) を開き、変更する DataTable を右クリックして、[追加/ 列] を選択します。 に新しい列を追加します CategoriesDataTable (図 5 を参照)。

CategoriesDataSource に新しい列を追加する

図 5: に新しい列を追加する CategoriesDataSource (フルサイズの画像を表示する場合はクリックします)

これにより、 という名前 Column1の新しい列が追加されます。これは、別の名前を入力するだけで変更できます。 この新しい列の名前を に NumberOfProducts変更します。 次に、この列のプロパティを構成する必要があります。 新しい列をクリックし、プロパティ ウィンドウに移動します。 図 6 に示すように、列の DataType プロパティを から System.StringSystem.Int32変更し、 プロパティを にTrue設定ReadOnlyします。

新しい列の DataType プロパティと ReadOnly プロパティを設定する

図 6: 新しい列の DataType プロパティと ReadOnly プロパティを設定する

CategoriesDataTableには列が含NumberOfProductsまれていますが、その値は対応する TableAdapter のクエリによって設定されません。 カテゴリ情報が GetCategories() 取得されるたびにそのような情報を返す場合は、 メソッドを更新してこの情報を返すことができます。 ただし、まれなインスタンス (このチュートリアルの場合など) のカテゴリに関連付けられている製品の数のみを取得する必要がある場合は、そのままに GetCategories() して、この情報を返す新しいメソッドを作成できます。 この後者の方法を使用して、 という名前 GetCategoriesAndNumberOfProducts()の新しいメソッドを作成してみましょう。

この新しい GetCategoriesAndNumberOfProducts() メソッドを追加するには、 を CategoriesTableAdapter 右クリックし、 [新しいクエリ] を選択します。 これにより、TableAdapter クエリ構成ウィザードが表示されます。これは、前のチュートリアルで何度も使用しました。 このメソッドでは、クエリで行を返すアドホック SQL ステートメントが使用されていることを示して、ウィザードを開始します。

アドホック SQL ステートメントを使用して メソッドを作成する

図 7: アドホック SQL ステートメントを使用してメソッドを作成する (クリックするとフルサイズの画像が表示されます)

SQL ステートメントは行を返します

図 8: SQL ステートメントは行を返します (クリックするとフルサイズの画像が表示されます)

次のウィザード画面で、クエリを使用するように求められます。 各カテゴリの 、 CategoryIDCategoryNameおよび フィールドと Description 、カテゴリに関連付けられている製品の数を返すには、次 SELECT のステートメントを使用します。

SELECT CategoryID, CategoryName, Description,
       (SELECT COUNT(*) FROM Products p WHERE p.CategoryID = c.CategoryID)
            as NumberOfProducts
FROM Categories c

使用するクエリを指定する

図 9: 使用するクエリを指定する (クリックするとフルサイズの画像が表示されます)

カテゴリに関連付けられている製品の数を計算するサブクエリは、 として NumberOfProductsエイリアス化されることに注意してください。 この名前付け一致により、このサブクエリによって返される値が s NumberOfProducts 列にCategoriesDataTable関連付けられます。

このクエリを入力した後、最後の手順は新しいメソッドの名前を選択することです。 GetCategoriesAndNumberOfProducts DataTable の塗りつぶしと DataTable パターンの取得に それぞれ と を使用FillWithNumberOfProductsします。

新しい TableAdapter のメソッドに FillWithNumberOfProducts と GetCategoriesAndNumberOfProducts という名前を付けます

図 10: 新しい TableAdapter のメソッドに名前を FillWithNumberOfProductsGetCategoriesAndNumberOfProducts け、(フルサイズの画像を表示する をクリックします)

この時点で、データ アクセス層はカテゴリごとの製品数を含むように拡張されています。 すべてのプレゼンテーション レイヤーは、個別のビジネス ロジック レイヤーを介して DAL へのすべての呼び出しをルーティングするため、対応する GetCategoriesAndNumberOfProducts メソッドを クラスに追加する CategoriesBLL 必要があります。

<System.ComponentModel.DataObjectMethodAttribute _
    (System.ComponentModel.DataObjectMethodType.Select, False)> _
Public Function GetCategoriesAndNumberOfProducts() As Northwind.CategoriesDataTable
    Return Adapter.GetCategoriesAndNumberOfProducts()
End Function

DAL と BLL が完了したら、 でこのデータを Repeater CategoriesAndProducts.aspxにバインドするCategories準備ができました。 [イベント ハンドラー] セクションの [製品 ItemDataBound 数の決定] セクションから Repeater の ObjectDataSource を既に作成している場合は、この ObjectDataSource を削除し、Repeater の DataSourceID プロパティ設定を削除します。また、ASP.NET 分離コード クラスの構文を削除して、イベント ハンドラーから Repeater の ItemDataBound イベントのワイヤを解除 Handles Categories.OnItemDataBound します。

Repeater が元の状態に戻った状態で、Repeater のスマート タグを使用して という名前 CategoriesDataSource の新しい ObjectDataSource を追加します。 クラスを使用するように ObjectDataSource を CategoriesBLL 構成しますが、 メソッドを GetCategories() 使用するのではなく、 を代わりに使用 GetCategoriesAndNumberOfProducts() します (図 11 を参照)。

GetCategoriesAndNumberOfProducts メソッドを使用するように ObjectDataSource を構成する

図 11: メソッドを使用 GetCategoriesAndNumberOfProducts するように ObjectDataSource を構成する (クリックするとフルサイズの画像が表示されます)

次にItemTemplate、 を更新して、LinkButton のTextプロパティがデータ バインド構文を使用して宣言的に割り当てられ、 フィールドと NumberOfProducts データ フィールドの両方がCategoryName含まれるようにします。 Repeater と CategoriesDataSource ObjectDataSource の完全な宣言型マークアップは次のとおりです。

<asp:Repeater ID="Categories" runat="server" DataSourceID="CategoriesDataSource">
    <HeaderTemplate>
        <ul>
    </HeaderTemplate>
    <ItemTemplate>
        <li><asp:LinkButton runat="server" ID="ViewCategory"
                Text='<%# String.Format("{0} ({1:N0})", _
                    Eval("CategoryName"), Eval("NumberOfProducts")) %>' />
        </li>
    </ItemTemplate>
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategoriesAndNumberOfProducts" TypeName="CategoriesBLL">
</asp:ObjectDataSource>

DAL を更新して列を含 NumberOfProducts めることでレンダリングされる出力は、イベント ハンドラー アプローチの使用 ItemDataBound と同じです (カテゴリ名と製品数を示す Repeater のスクリーン ショットを確認するには、図 4 を参照してください)。

手順 3: 選択したカテゴリの製品を表示する

この時点で、リピータには Categories 、カテゴリの一覧と各カテゴリの製品数が表示されます。 Repeater は、クリックするとポストバックが発生するカテゴリごとに LinkButton を使用します。この時点で、選択したカテゴリの製品を DataList に表示する CategoryProducts 必要があります。

私たちが直面する課題の 1 つは、選択したカテゴリの製品だけを DataList に表示する方法です。 「 Master/Detail Using a Selectable Master GridView with a DetailsView with a DetailsView 」チュートリアルでは、行を選択できる GridView を作成し、選択した行の詳細を同じページの DetailsView に表示する方法について説明しました。 GridView s ObjectDataSource は s メソッドを使用してすべての製品に関する情報をProductsBLLGetProducts()返し、DetailsView の ObjectDataSource は メソッドを使用して選択した製品に関する情報をGetProductsByProductID(productID)取得しました。 パラメーター値は productID 、GridView の SelectedValue プロパティの値に関連付けることで宣言によって提供されました。 残念ながら、Repeater には SelectedValue プロパティがないため、パラメーター ソースとして機能することはできません。

注意

これは、リピータで LinkButton を使用するときに発生する課題の 1 つです。 ハイパーリンクを使用してクエリ文字列を渡 CategoryID していた場合は、その QueryString フィールドをパラメーターの値のソースとして使用できます。

ただし、Repeater の SelectedValue プロパティがないことを心配する前に、まず DataList を ObjectDataSource にバインドし、その ItemTemplateを指定します。

DataList のスマート タグから、 という名前CategoryProductsDataSourceの新しい ObjectDataSource を追加し、クラスの GetProductsByCategoryID(categoryID) メソッドをProductsBLL使用するように構成します。 このチュートリアルの DataList には読み取り専用インターフェイスが用意されているため、INSERT タブ、UPDATE タブ、DELETE タブのドロップダウン リストを (None) に自由に設定できます。

ProductBLL クラスの GetProductsByCategoryID(categoryID) メソッドを使用するように ObjectDataSource を構成する

図 12: クラスの GetProductsByCategoryID(categoryID) メソッドを使用ProductsBLLするように ObjectDataSource を構成する (フルサイズの画像を表示する をクリックします)

メソッドは GetProductsByCategoryID(categoryID) 入力パラメーター (categoryID) を必要とするため、データ ソースの構成ウィザードではパラメーターのソースを指定できます。 カテゴリが GridView または DataList に一覧表示されている場合は、パラメーター ソース ドロップダウン リストを Control に、ControlID をデータ Web コントロールの に ID 設定します。 ただし、Repeater にはプロパティがないため、 SelectedValue パラメーター ソースとして使用することはできません。 チェックすると、ControlID ドロップダウン リストに DataList の コントロール ID``CategoryProductsID 1 つだけ含まれていることがわかります。

ここでは、[パラメーター ソース] ドロップダウン リストを [なし] に設定します。 これで、カテゴリ LinkButton が Repeater でクリックされたときに、プログラムによってこのパラメーター値が割り当てられます。

categoryID パラメーターにパラメーター ソースを指定しない

図 13: パラメーターのパラメーター ソース categoryID を指定しない (フルサイズの画像を表示する をクリックします)

データ ソースの構成ウィザードが完了すると、Visual Studio によって DataList が ItemTemplate自動生成されます。 この既定値 ItemTemplate は、前のチュートリアルで使用したテンプレートに置き換えます。また、DataList の RepeatColumns プロパティを 2 に設定します。 これらの変更を行った後、DataList とそれに関連付けられている ObjectDataSource の宣言型マークアップは次のようになります。

<asp:DataList ID="CategoryProducts" runat="server" DataKeyField="ProductID"
    DataSourceID="CategoryProductsDataSource" RepeatColumns="2"
    EnableViewState="False">
    <ItemTemplate>
        <h5><%# Eval("ProductName") %></h5>
        <p>
            Supplied by <%# Eval("SupplierName") %><br />
            <%# Eval("UnitPrice", "{0:C}") %>
        </p>
    </ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="CategoryProductsDataSource"
    OldValuesParameterFormatString="original_{0}"  runat="server"
    SelectMethod="GetProductsByCategoryID" TypeName="ProductsBLL">
    <SelectParameters>
        <asp:Parameter Name="categoryID" Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

現在、 CategoryProductsDataSource ObjectDataSource の categoryID パラメーターは設定されていないため、ページを表示するときに製品は表示されません。 実行する必要がある操作は、Repeater でクリックしたカテゴリの に CategoryID 基づいて、このパラメーター値を設定することです。 2 つの課題が発生します。1 つ目は、リピータの ItemTemplate LinkButton がいつクリックされたかを判断する方法と、リンク ボタンがクリックされた対応するカテゴリの を特定 CategoryID する方法です。

Button コントロールや ImageButton コントロールなどの LinkButton には、ClickイベントとイベントがありますCommand。 このイベントは Click 、LinkButton がクリックされたことに注意するように設計されています。 ただし、LinkButton がクリックされたことに加えて、イベント ハンドラーに追加情報を渡す必要もあります。 この場合は、LinkButton とCommandNameCommandArgumentプロパティにこの追加情報を割り当てることができます。 次に、LinkButton がクリックされると、そのCommandイベントが (イベントではなくClick) 発生し、イベント ハンドラーに および CommandArgument プロパティのCommandName値が渡されます。

Command Repeater のテンプレート内からイベントが発生すると、Repeater イベントItemCommand発生し、クリックした LinkButton (または Button または ImageButton) の 値と CommandArgument 値が渡されますCommandName。 したがって、リピータのカテゴリ LinkButton がいつクリックされたかを判断するには、次の操作を行う必要があります。

  1. CommandName Repeater ItemTemplate の LinkButton のプロパティを何らかの値に設定します (ListProducts を使用しました)。 この CommandName 値を設定すると、LinkButton がクリックされたときに LinkButton イベント Command が発生します。
  2. LinkButton の CommandArgument プロパティを、現在の項目の の値に CategoryID設定します。
  3. Repeater の ItemCommand イベントのイベント ハンドラーを作成します。 イベント ハンドラーで、ObjectDataSource の CategoryID パラメーターを渡された の値にCommandArgument設定CategoryProductsDataSourceします。

Categories Repeater の次 ItemTemplate のマークアップは、手順 1 と 2 を実装します。 データバインド構文を CommandArgument 使用して、値にデータ項目がどのように CategoryID 割り当てられるかに注意してください。

<ItemTemplate>
    <li>
        <asp:LinkButton CommandName="ListProducts"  runat="server"
            CommandArgument='<%# Eval("CategoryID") %>' ID="ViewCategory"
            Text='<%# string.Format("{0} ({1:N0})", _
                Eval("CategoryName"), Eval("NumberOfProducts")) %>'>
        </asp:LinkButton>
    </li>
</ItemTemplate>

イベント ハンドラーをItemCommand作成するときは常に、常に最初に受信CommandNameCommandをチェックすることをお勧めします。これは、Repeater 内の Button、LinkButton、または ImageButton によって発生したイベントによってイベントがItemCommand発生するためです。 現在、このような LinkButton は 1 つだけありますが、将来的には (またはチームの別の開発者)、クリックすると同じ ItemCommand イベント ハンドラーを発生させるボタン Web コントロールを Repeater に追加する可能性があります。 そのため、常に プロパティをチェックCommandNameし、必要な値に一致する場合にのみプログラムロジックを続行することをお勧めします。

渡されたCommandName値が ListProducts と等しいことを確認した後、イベント ハンドラーは ObjectDataSource の CategoryID パラメーターを渡された CommandArgumentの値に割り当てますCategoryProductsDataSource。 ObjectDataSource に SelectParameters 対するこの変更により、DataList が自動的にデータ ソースに再バインドされ、新しく選択されたカテゴリの製品が表示されます。

Protected Sub Categories_ItemCommand(source As Object, e As RepeaterCommandEventArgs) _
    Handles Categories.ItemCommand
    ' If it's the "ListProducts" command that has been issued...
    If String.Compare(e.CommandName, "ListProducts", True) = 0 Then
        ' Set the CategoryProductsDataSource ObjectDataSource's CategoryID parameter
        ' to the CategoryID of the category that was just clicked (e.CommandArgument)...
        CategoryProductsDataSource.SelectParameters("CategoryID").DefaultValue = _
            e.CommandArgument.ToString()
    End If
End Sub

これらの追加により、チュートリアルは完了です。 少し時間を取ってブラウザーでテストします。 図 14 は、最初にページにアクセスしたときの画面を示しています。 カテゴリはまだ選択されていないので、製品は表示されません。 [生産] などのカテゴリをクリックすると、[製品] カテゴリの製品が 2 列ビューで表示されます (図 15 を参照)。

ページに初めてアクセスしたときに製品が表示されない

図 14: 最初にページにアクセスしたときに製品が表示されない (フルサイズの画像を表示する をクリックします)

右に一致する製品Lists [商品] カテゴリをクリックする

図 15: 右に一致する製品Lists [生産] カテゴリをクリックします (フルサイズの画像を表示する をクリックします)

まとめ

このチュートリアルと前のチュートリアルで見たように、マスター/詳細レポートは 2 ページに分散することも、1 ページに統合することもできます。 ただし、マスター/詳細レポートを 1 つのページに表示すると、マスター レコードと詳細レコードをページに最適にレイアウトする方法に関するいくつかの課題が発生します。 マスター /詳細選択可能なマスター グリッド ビューと Details DetailsView を使用する チュートリアルでは、マスター レコードの上に詳細レコードが表示されていました。このチュートリアルでは、CSS 手法を使用して、マスター レコードを詳細の左側に浮動させます。

マスター/詳細レポートの表示に加えて、各カテゴリに関連付けられている製品の数を取得する方法と、LinkButton (または Button または ImageButton) が Repeater 内からクリックされたときにサーバー側ロジックを実行する方法についても説明しました。

このチュートリアルでは、DataList と Repeater を使用してマスター/詳細レポートの検査を完了します。 次の一連のチュートリアルでは、DataList コントロールに編集機能と削除機能を追加する方法について説明します。

プログラミングに満足!

もっと読む

このチュートリアルで説明するトピックの詳細については、次のリソースを参照してください。

  • Floatutorial CSS を使用したフローティング CSS 要素に関するチュートリアル
  • CSS を使用 した要素の配置に関する詳細情報の CSS 配置
  • 配置 に s と他の HTML 要素を使用して HTML を使用して <table> コンテンツをレイアウトする

著者について

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

特別な感謝

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