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

作成者: 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 を使用して、 浮動を介して、ある要素を別の要素の右または左に配置することもできます。 DataList の左側に Repeater を浮動させることで、選択したカテゴリの製品の左側に項目の箇条書きを表示できます

フォルダーからページをCategoriesAndProducts.aspxDataListRepeaterFiltering開き、ページに Repeater と DataList を追加します。 Repeater s ID を に Categories 設定し、DataList を に設定します 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; 、2 番目の要素の左側に最初 <div> の要素を浮動します。 と padding-right の設定はwidth、最初<div>の s と、要素のwidthコンテンツとその右余白の間に<div>追加されるパディングの量を示します。 CSS のフローティング要素の詳細については、 Floatutorial を参照してください。

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

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

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

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

リピータが DataList の左側に浮動

図 2: リピータが DataList の左側に浮動 (フルサイズの画像を表示する をクリックします)

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

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

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

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

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

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

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

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

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" /></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 プロパティが設定されていません。 カテゴリ名を表示するだけの場合は、Databinding 構文を使用して、次のように Text プロパティを宣言的に設定します。

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

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

protected void Categories_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    // Make sure we're working with a data item...
    if (e.Item.ItemType == ListItemType.Item ||
        e.Item.ItemType == ListItemType.AlternatingItem)
    {
        // Reference the CategoriesRow instance bound to this RepeaterItem
        Northwind.CategoriesRow category =
            (Northwind.CategoriesRow) ((System.Data.DataRowView) e.Item.DataItem).Row;
        // Determine how many products are in this category
        NorthwindTableAdapters.ProductsTableAdapter productsAPI =
            new NorthwindTableAdapters.ProductsTableAdapter();
        int productCount =
            productsAPI.GetProductsByCategoryID(category.CategoryID).Count;
        // Reference the ViewCategory LinkButton and set its Text property
        LinkButton ViewCategory = (LinkButton)e.Item.FindControl("ViewCategory");
        ViewCategory.Text =
            string.Format("{0} ({1:N0})", category.CategoryName, productCount);
    }
}

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

注意

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

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

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

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

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

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

CategoriesDataSource に新しい列を追加する

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

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

新しい列の 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関連付けられます。

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

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

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

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

[System.ComponentModel.DataObjectMethodAttribute
    (System.ComponentModel.DataObjectMethodType.Select, false)]
public Northwind.CategoriesDataTable GetCategoriesAndNumberOfProducts()
{
    return Adapter.GetCategoriesAndNumberOfProducts();
}

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

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

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

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

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

<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: 選択したカテゴリの製品を表示する

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

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

注意

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

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

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

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

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

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

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

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。 したがって、Repeater のカテゴリ LinkButton がいつクリックされたかを確認するには、次の操作を行う必要があります。

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

Categories Repeater の次 ItemTemplate のマークアップでは、手順 1 と 2 が実装されています。 databinding 構文を 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 イベント ハンドラーを作成するときは常に、最初に受信する CommandName 値を確認するのが賢明です。これは、Repeater 内の 任意の Button、LinkBut​​ton、または ImageButton によって発生した 任意の Command イベントによって、 ItemCommand イベントが発生するためです。 現在、このような LinkButton は 1 つだけですが、将来、(またはチームの別の開発者) は、クリックされると同じ ItemCommand イベント ハンドラーを発生させるボタン Web コントロールを Repeater に追加する可能性があります。 そのため、常に プロパティを確認 CommandName し、必要な値に一致する場合にのみプログラムロジックを続行することをお勧めします。

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

protected void Categories_ItemCommand(object source, RepeaterCommandEventArgs e)
{
    // If it's the "ListProducts" command that has been issued...
    if (string.Compare(e.CommandName, "ListProducts", true) == 0)
    {
        // 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();
    }
}

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

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

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

[生産] カテゴリをクリックすると、一致する製品が右側に一覧表示されます

図 15: [作成] カテゴリをクリックすると、一致する製品が右に一覧表示されます (フルサイズの画像を表示する場合はクリックします)

概要

このチュートリアルと前のチュートリアルで見たように、マスター/詳細レポートは 2 つのページに分散することも、1 ページに統合することもできます。 ただし、マスター/詳細レポートを 1 つのページに表示すると、ページ上のマスター レコードと詳細レコードを最適にレイアウトする方法に関するいくつかの課題が発生します。 詳細詳細 ビューを使用して選択可能なマスター グリッド ビューを使用するマスター/詳細 チュートリアルでは、マスター レコードの上に詳細レコードが表示されていました。このチュートリアルでは、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行をドロップしてください。