DataList または Repeater コントロールのデータを並べ替える (C#)

作成者: Scott Mitchell

PDF のダウンロード

このチュートリアルでは、DataList と Repeater に並べ替えのサポートを含める方法と、データをページングおよび並べ替えできる DataList または Repeater を構築する方法について説明します。

はじめに

前の チュートリアル では、DataList にページング サポートを追加する方法について説明しました。 オブジェクトを返すクラス (GetProductsAsPagedDataSource) にProductsBLL新しいメソッドをPagedDataSource作成しました。 DataList または Repeater にバインドすると、DataList または Repeater には、要求されたデータ ページだけが表示されます。 この手法は、組み込みの既定のページング機能を提供するために GridView、DetailsView、および FormView コントロールによって内部的に使用される手法と似ています。

GridView には、ページングのサポートに加えて、すぐに使用できる並べ替えのサポートも含まれています。 DataList と Repeater はどちらも組み込みの並べ替え機能を提供しません。ただし、並べ替え機能は少しコードで追加できます。 このチュートリアルでは、DataList と Repeater に並べ替えのサポートを含める方法と、データをページングおよび並べ替えできる DataList または Repeater を構築する方法について説明します。

並べ替えのレビュー

レポート データのページングと並べ替え 」のチュートリアルで説明したように、GridView コントロールは、すぐに使える並べ替えのサポートを提供します。 各 GridView フィールドには、データを並べ替えるデータ フィールドを示す が関連付けられます SortExpression。 GridView の AllowSorting プロパティが に true設定されている場合、プロパティ値を持つ SortExpression 各 GridView フィールドには、そのヘッダーが LinkButton としてレンダリングされます。 ユーザーが特定の GridView フィールドのヘッダーをクリックすると、ポストバックが発生し、クリックしたフィールドの SortExpressionに従ってデータが並べ替えられます。

GridView コントロールには、データの SortExpression 並べ替えの基準となる GridView フィールドの を格納 SortExpression する プロパティもあります。 さらに、プロパティは、 SortDirection データを昇順または降順で並べ替えるかどうかを示します (ユーザーが特定の GridView フィールドのヘッダー リンクを 2 回連続してクリックすると、並べ替え順序が切り替えられます)。

GridView は、データ ソース コントロールにバインドされると、その SortExpression プロパティと SortDirection プロパティをデータ ソース コントロールに引き離します。 データ ソース コントロールは、データを取得し、指定された SortExpression プロパティと SortDirection プロパティに従って並べ替えます。 データを並べ替えたら、データ ソース コントロールから GridView に返されます。

DataList コントロールまたは Repeater コントロールを使用してこの機能をレプリケートするには、次の操作を行う必要があります。

  • 並べ替えインターフェイスを作成する
  • 並べ替えの基準となるデータ フィールドと、昇順または降順のどちらで並べ替えるかを覚えておいてください
  • ObjectDataSource に、特定のデータ フィールドでデータを並べ替えるよう指示する

手順 3 と 4 では、これら 3 つのタスクに取り組みます。 その後、DataList または Repeater にページングと並べ替えの両方のサポートを含める方法について説明します。

手順 2: リピータで製品を表示する

並べ替えに関連する機能の実装について心配する前に、まず製品を Repeater コントロールに一覧表示します。 まず、フォルダー内の Sorting.aspx ページを PagingSortingDataListRepeater 開きます。 Web ページに Repeater コントロールを追加し、そのプロパティを IDSortableProducts設定します。 Repeater のスマート タグから、 という名前ProductsDataSourceの新しい ObjectDataSource を作成し、クラスの GetProducts() メソッドからデータをProductsBLL取得するように構成します。 [INSERT]、[UPDATE]、[DELETE] タブのドロップダウン リストから [(なし)] オプションを選択します。

ObjectDataSource を作成し、GetProductsAsPagedDataSource() メソッドを使用するように構成する

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

[UPDATE]、[INSERT]、[DELETE] タブの Drop-Down Lists を [(なし)] に設定します

図 2: UPDATE タブ、INSERT タブ、DELETE タブの Drop-Down Lists を [(なし)] に設定します (フルサイズの画像を表示する場合は、ここをクリックします)

DataList とは異なり、Visual Studio では、データ ソースにバインドした後に Repeater コントロールの が自動的に作成 ItemTemplate されることはありません。 さらに、Repeater コントロールのスマート タグに DataList の [テンプレートの編集] オプションがないため、これを ItemTemplate 宣言によって追加する必要があります。 前のチュートリアルと同じもの ItemTemplate を使用して、製品名、仕入先、カテゴリを表示してみましょう。

ItemTemplate追加した後、Repeater と ObjectDataSource の宣言型マークアップは次のようになります。

<asp:Repeater ID="SortableProducts" DataSourceID="ProductsDataSource"
    EnableViewState="False" runat="server">
    <ItemTemplate>
        <h4><asp:Label ID="ProductNameLabel" runat="server"
            Text='<%# Eval("ProductName") %>'></asp:Label></h4>
        Category:
        <asp:Label ID="CategoryNameLabel" runat="server"
            Text='<%# Eval("CategoryName") %>'></asp:Label><br />
        Supplier:
        <asp:Label ID="SupplierNameLabel" runat="server"
            Text='<%# Eval("SupplierName") %>'></asp:Label><br />
        <br />
        <br />
    </ItemTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}" TypeName="ProductsBLL"
    SelectMethod="GetProducts">
</asp:ObjectDataSource>

図 3 は、ブラウザーで表示された場合のこのページを示しています。

各製品名、仕入先、およびカテゴリが表示されます

図 3: 各製品名、仕入先、およびカテゴリが表示されている (フルサイズの画像を表示する をクリックします)

手順 3: ObjectDataSource にデータの並べ替えを指示する

Repeater に表示されるデータを並べ替えるには、データの並べ替えの基準となる並べ替え式を ObjectDataSource に通知する必要があります。 ObjectDataSource がデータを取得する前に、最初にそのイベントをSelecting発生させます。これにより、並べ替え式を指定する機会が提供されます。 イベント ハンドラーには Selecting 、 型 ObjectDataSourceSelectingEventArgsの オブジェクトが渡されます。このオブジェクトには 型 という名前 ArgumentsDataSourceSelectArgumentsプロパティがあります。 クラスはDataSourceSelectArguments、データのコンシューマーからデータ ソース 管理にデータ関連の要求を渡すために設計されており、 プロパティがSortExpression含まれています。

ASP.NET ページから ObjectDataSource に並べ替え情報を渡すには、イベントのイベント ハンドラーを Selecting 作成し、次のコードを使用します。

protected void ProductsDataSource_Selecting
    (object sender, ObjectDataSourceSelectingEventArgs e)
{
    e.Arguments.SortExpression = sortExpression;
}

sortExpression 値には、データを並べ替えるデータ フィールドの名前 (ProductName など) を割り当てる必要があります。 並べ替え方向に関連するプロパティがないため、データを降順で並べ替える場合は、文字列 DESC を sortExpression 値 (ProductName DESC など) に追加します。

sortExpression に対していくつかのハードコーディングされた値を試し、ブラウザーで結果をテストします。 図 4 に示すように、 sortExpression として ProductName DESC を使用すると、製品は名前のアルファベット順に逆順に並べ替えられます。

製品は名前で並べ替えられます(アルファベット順に逆順に並べ替えられます)

図 4: 製品の名前がアルファベット順に並べ替えられている (フルサイズの画像を表示する をクリックします)

手順 4: 並べ替えインターフェイスを作成し、並べ替えの式と方向を記憶する

GridView で並べ替えのサポートを有効にすると、並べ替え可能な各フィールドのヘッダー テキストが LinkButton に変換され、クリックすると、それに応じてデータが並べ替えられます。 このような並べ替えインターフェイスは、データが列にきちんとレイアウトされている GridView にとって理にかなっています。 ただし、DataList コントロールと Repeater コントロールには、別の並べ替えインターフェイスが必要です。 データの一覧 (データグリッドではなく) の一般的な並べ替えインターフェイスは、データを並べ替えることができるフィールドを提供するドロップダウン リストです。 このチュートリアルでは、このようなインターフェイスを実装してみましょう。

Repeater の上に DropDownList Web コントロールを SortableProducts 追加し、そのプロパティを IDSortBy設定します。 プロパティ ウィンドウから、プロパティの省略記号をItemsクリックして ListItem コレクション エディターを表示します。 、、および SupplierName フィールドでデータを並べ替えるには、 CategoryNameProductNameを追加ListItemします。 また、 を ListItem 追加して、製品の名前をアルファベット順に逆順に並べ替えます。

プロパティは任意の ListItemText 値 (Name など) に設定できますが Value 、プロパティはデータ フィールドの名前 (ProductName など) に設定する必要があります。 結果を降順で並べ替えるには、ProductName DESC のように、文字列 DESC をデータ フィールド名に追加します。

並べ替え可能なデータ フィールドごとに ListItem を追加する

図 5: 並べ替え可能なデータ フィールドごとに を追加 ListItem する

最後に、DropDownList の右側に Button Web コントロールを追加します。 その を IDRefreshRepeater 設定し、その Text プロパティを Refresh に設定します。

ListItem 作成し、[更新] ボタンを追加すると、DropDownList と Button の宣言構文は次のようになります。

<asp:DropDownList ID="SortBy" runat="server">
    <asp:ListItem Value="ProductName">Name</asp:ListItem>
    <asp:ListItem Value="ProductName DESC">Name (Reverse Order)
        </asp:ListItem>
    <asp:ListItem Value="CategoryName">Category</asp:ListItem>
    <asp:ListItem Value="SupplierName">Supplier</asp:ListItem>
</asp:DropDownList>
<asp:Button runat="server" ID="RefreshRepeater" Text="Refresh" />

並べ替え DropDownList が完了したら、次に ObjectDataSource の Selecting イベント ハンドラーを更新して、ハードコーディングされた並べ替え式ではなく、選択した SortBy``ListItem s Value プロパティを使用するようにする必要があります。

protected void ProductsDataSource_Selecting
    (object sender, ObjectDataSourceSelectingEventArgs e)
{
    // Have the ObjectDataSource sort the results by the selected
    // sort expression
    e.Arguments.SortExpression = SortBy.SelectedValue;
}

この時点で最初にページにアクセスすると、製品は既定で選択されているため、SortByListItem最初はデータ フィールドでProductName並べ替えられます (図 6 を参照)。 [カテゴリ] などの別の並べ替えオプションを選択し、[更新] をクリックすると、ポストバックが発生し、カテゴリ名でデータが並べ替えられます (図 7 を参照)。

製品は最初に名前で並べ替えられます

図 6: 製品は最初に名前で並べ替えられています (クリックするとフルサイズの画像が表示されます)

製品がカテゴリ別に並べ替えられるようになりました

図 7: 製品がカテゴリ別に並べ替えられるようになりました (クリックするとフルサイズの画像が表示されます)

注意

[更新] ボタンをクリックすると、Repeater のビュー ステートが無効になっているため、データが自動的に再並べ替えられます。これにより、Repeater はポストバックごとにデータ ソースに再バインドされます。 Repeater のビュー ステートを有効のままにした場合、並べ替えドロップダウン リストを変更しても、並べ替え順序には影響しません。 これを解決するには、Refresh Button の Click イベントのイベント ハンドラーを作成し、Repeater をデータ ソースに再バインドします (Repeater の DataBind() メソッドを呼び出します)。

並べ替え式と方向の記憶

並べ替え不可能な関連ポストバックが発生する可能性があるページで並べ替え可能な DataList または Repeater を作成する場合、並べ替え式と方向をポストバック間で記憶することが不可欠です。 たとえば、このチュートリアルで Repeater を更新して、各製品に [削除] ボタンを追加したとします。 ユーザーが [削除] ボタンをクリックすると、選択した製品を削除し、データを Repeater に再バインドするコードが実行されます。 ポストバックの間で並べ替えの詳細が保持されない場合、画面に表示されるデータは元の並べ替え順序に戻ります。

このチュートリアルでは、DropDownList によって並べ替え式と方向がビュー ステートに暗黙的に保存されます。 たとえば、さまざまな並べ替えオプションを提供する LinkButton を使用して別の並べ替えインターフェイスを使用していた場合は、ポストバック間の並べ替え順序を覚えておく必要があります。 これを実現するには、並べ替えパラメーターをページのビュー ステートに格納するか、クエリ文字列に並べ替えパラメーターを含めるか、その他の状態の永続化手法を使用します。

このチュートリアルの今後の例では、並べ替えの詳細をページのビューステートに保持する方法について説明します。

手順 5: 既定のページングを使用する DataList に並べ替えのサポートを追加する

前の チュートリアル では、DataList を使用して既定のページングを実装する方法について説明しました。 この前の例を拡張して、ページ データを並べ替える機能を含めます。 まず、 フォルダー内の SortingWithDefaultPaging.aspx ページと Paging.aspx ページを PagingSortingDataListRepeater 開きます。 ページから Paging.aspx [ソース] ボタンをクリックして、ページの宣言型マークアップを表示します。 選択したテキストをコピーし (図 8 を参照)、タグ間の の SortingWithDefaultPaging.aspx 宣言型マークアップに <asp:Content> 貼り付けます。

asp:Content> タグの宣言型マークアップを <Paging.aspx から SortingWithDefaultPaging.aspx にレプリケートする

図 8: タグ内の宣言型マークアップを <asp:Content> から Paging.aspx にレプリケートします SortingWithDefaultPaging.aspx (フルサイズの画像を表示する 場合はクリックします)

宣言型マークアップをコピーした後、ページの分離コード クラスのメソッドとプロパティを Paging.aspx の分離コード クラスにコピーします SortingWithDefaultPaging.aspx。 次に、ブラウザーでページを SortingWithDefaultPaging.aspx 表示します。 と同じ機能と外観 Paging.aspxを示す必要があります。

既定のページングと並べ替え方法を含むように ProductsBLL を拡張する

前のチュートリアルでは、 オブジェクトを GetProductsAsPagedDataSource(pageIndex, pageSize) 返す メソッドを ProductsBLL クラスに作成しました PagedDataSource 。 この PagedDataSource オブジェクトには ( BLL s GetProducts() メソッドを介して) すべての製品が設定されましたが、DataList にバインドされている場合は、指定された pageIndex および pageSize 入力パラメーターに対応するレコードのみが表示されました。

このチュートリアルの前半では、ObjectDataSource のイベント ハンドラーから並べ替え式を指定することで、並べ替えの Selecting サポートを追加しました。 これは、ObjectDataSource が、 メソッドによって返される と同様 ProductsDataTable に、並べ替え可能なオブジェクトを返すときに適切に GetProducts() 機能します。 ただし、 PagedDataSource メソッドによって GetProductsAsPagedDataSource 返される オブジェクトは、内部データ ソースの並べ替えをサポートしていません。 代わりに、 メソッドから返された結果を に配置するGetProducts()前にPagedDataSource並べ替える必要があります。

これを実現するには、 クラスに新しいメソッドを ProductsBLL 作成します GetProductsSortedAsPagedDataSource(sortExpression, pageIndex, pageSize)。 メソッドによってGetProducts()返される をProductsDataTable並べ替えるには、既定の の プロパティをSort指定しますDataTableView

[System.ComponentModel.DataObjectMethodAttribute
    (System.ComponentModel.DataObjectMethodType.Select, false)]
public PagedDataSource GetProductsSortedAsPagedDataSource
    (string sortExpression, int pageIndex, int pageSize)
{
    // Get ALL of the products
    Northwind.ProductsDataTable products = GetProducts();
    // Sort the products
    products.DefaultView.Sort = sortExpression;
    // Limit the results through a PagedDataSource
    PagedDataSource pagedData = new PagedDataSource();
    pagedData.DataSource = products.DefaultView;
    pagedData.AllowPaging = true;
    pagedData.CurrentPageIndex = pageIndex;
    pagedData.PageSize = pageSize;
    return pagedData;
}

メソッドは GetProductsSortedAsPagedDataSource 、前のチュートリアルで作成した GetProductsAsPagedDataSource メソッドとは若干異なります。 特に、 GetProductsSortedAsPagedDataSource は追加の入力パラメーターsortExpressionを受け取り、この値を SortDefaultViewプロパティにProductDataTable割り当てます。 後で数行のコードを実行するとPagedDataSource、オブジェクトの DataSource に がProductDataTableDefaultView割り当てられます。

GetProductsSortedAsPagedDataSource メソッドの呼び出しと SortExpression 入力パラメーターの値の指定

メソッドが GetProductsSortedAsPagedDataSource 完了したら、次の手順では、このパラメーターの値を指定します。 の SortingWithDefaultPaging.aspx ObjectDataSource は現在、 メソッドを呼び出 GetProductsAsPagedDataSource すように構成されており、コレクションで指定されている 2 つの入力パラメーターを 2 つの QueryStringParameters入力パラメーターに SelectParameters 渡します。 これら 2 つQueryStringParametersは、メソッドの pageIndex パラメーターと pageSize パラメーターのソースGetProductsAsPagedDataSourceが querystring フィールドpageIndexpageSizeから取得されることを示します。

ObjectDataSource の プロパティを SelectMethod 更新して、新しい GetProductsSortedAsPagedDataSource メソッドを呼び出すようにします。 次に、querystring フィールド から sortExpression 入力パラメーターにアクセスできるように、新しい QueryStringParameter を追加しますsortExpression。 s DefaultValueQueryStringParameter ProductName に設定します。

これらの変更の後、ObjectDataSource の宣言型マークアップは次のようになります。

<asp:ObjectDataSource ID="ProductsDefaultPagingDataSource"
    OldValuesParameterFormatString="original_{0}" TypeName="ProductsBLL"
    SelectMethod="GetProductsSortedAsPagedDataSource"
    OnSelected="ProductsDefaultPagingDataSource_Selected" runat="server">
    <SelectParameters>
        <asp:QueryStringParameter DefaultValue="ProductName"
            Name="sortExpression" QueryStringField="sortExpression"
            Type="String" />
        <asp:QueryStringParameter DefaultValue="0" Name="pageIndex"
            QueryStringField="pageIndex" Type="Int32" />
        <asp:QueryStringParameter DefaultValue="4" Name="pageSize"
            QueryStringField="pageSize" Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

この時点で、ページはその結果を SortingWithDefaultPaging.aspx 製品名のアルファベット順に並べ替えます (図 9 を参照)。 これは、既定では、ProductName の値がメソッドの sortExpression パラメーターとしてGetProductsSortedAsPagedDataSource渡されるためです。

既定では、結果は ProductName で並べ替えられます

図 9: 既定では、結果は並 ProductName べ替えられます (フルサイズの画像を表示する場合はクリックします)

クエリ文字列フィールド (結果などSortingWithDefaultPaging.aspx?sortExpression=CategoryName) をsortExpression手動で追加すると、指定した sortExpressionによって並べ替えられます。 ただし、別のデータ ページに移動する場合、この sortExpression パラメーターは querystring に含まれません。 実際に、[次へ] または [最後のページ] ボタンをクリックすると、 に Paging.aspx戻ります。 さらに、現在、並べ替えインターフェイスはありません。 ユーザーがページングされたデータの並べ替え順序を変更できる唯一の方法は、クエリ文字列を直接操作することです。

並べ替えインターフェイスの作成

まず、 メソッドをRedirectUser更新してユーザーを (ではなくPaging.aspx) にSortingWithDefaultPaging.aspx送信し、クエリ文字列に値をsortExpression含める必要があります。 読み取り専用のページ レベルの名前付き SortExpression プロパティも追加する必要があります。 このプロパティは、前の PageIndex チュートリアルで作成した プロパティや プロパティと PageSize 同様に、querystring フィールドが存在する場合は値を返し、それ以外の sortExpression 場合は既定値 ( ProductName ) を返します。

現在、 メソッドは RedirectUser 、表示するページのインデックスを 1 つの入力パラメーターのみを受け入れます。 ただし、クエリ文字列で指定されたもの以外の並べ替え式を使用して、ユーザーを特定のデータ ページにリダイレクトしたい場合があります。 すぐに、このページの並べ替えインターフェイスを作成します。これには、指定した列でデータを並べ替えるための一連の Button Web コントロールが含まれます。 これらのボタンのいずれかがクリックされると、適切な並べ替え式の値を渡すユーザーをリダイレクトします。 この機能を提供するには、 メソッドの 2 つのバージョンを RedirectUser 作成します。 1 つ目は表示するページ インデックスのみを受け入れ、2 つ目はページ インデックスと並べ替え式を受け入れます。

private string SortExpression
{
    get
    {
        if (!string.IsNullOrEmpty(Request.QueryString["sortExpression"]))
            return Request.QueryString["sortExpression"];
        else
            return "ProductName";
    }
}
private void RedirectUser(int sendUserToPageIndex)
{
    // Use the SortExpression property to get the sort expression
    // from the querystring
    RedirectUser(sendUserToPageIndex, SortExpression);
}
private void RedirectUser(int sendUserToPageIndex, string sendUserSortingBy)
{
   // Send the user to the requested page with the requested sort expression
   Response.Redirect(string.Format(
      "SortingWithDefaultPaging.aspx?pageIndex={0}&pageSize={1}&sortExpression={2}",
      sendUserToPageIndex, PageSize, sendUserSortingBy));
}

このチュートリアルの最初の例では、DropDownList を使用して並べ替えインターフェイスを作成しました。 この例では、DataList コントロールの上に配置された 3 つのボタン Web コントロールを使用して、 で ProductName並べ替え、1 つを に CategoryName、もう 1 つを に使用 SupplierNameします。 3 つのボタン Web コントロールを追加し、それらのコントロールとTextプロパティをID適切に設定します。

<p>
    <asp:Button runat="server" id="SortByProductName"
        Text="Sort by Product Name" />
    <asp:Button runat="server" id="SortByCategoryName"
        Text="Sort by Category" />
    <asp:Button runat="server" id="SortBySupplierName"
        Text="Sort by Supplier" />
</p>

次に Click 、それぞれのイベント ハンドラーを作成します。 イベント ハンドラーは メソッドを RedirectUser 呼び出し、適切な並べ替え式を使用してユーザーを最初のページに返す必要があります。

protected void SortByProductName_Click(object sender, EventArgs e)
{
    // Sort by ProductName
    RedirectUser(0, "ProductName");
}
protected void SortByCategoryName_Click(object sender, EventArgs e)
{
    // Sort by CategoryName
    RedirectUser(0, "CategoryName");
}
protected void SortBySupplierName_Click(object sender, EventArgs e)
{
    // Sort by SupplierName
    RedirectUser(0, "SupplierName");
}

最初にページにアクセスすると、データは製品名のアルファベット順に並べ替えられます (図 9 を参照)。 [次へ] ボタンをクリックしてデータの 2 ページ目に進み、[カテゴリ別に並べ替え] ボタンをクリックします。 これにより、カテゴリ名で並べ替えられたデータの最初のページに戻ります (図 10 を参照)。 同様に、[仕入先別に並べ替え] ボタンをクリックすると、データの最初のページから仕入先別にデータが並べ替えられます。 並べ替えの選択は、データのページング時に記憶されます。 図 11 は、カテゴリ別に並べ替えてからデータの 13 ページ目に進むページを示しています。

製品はカテゴリ別に並べ替えられます

図 10: 製品はカテゴリ別に並べ替えられています (フルサイズの画像を表示する場合はクリックします)

並べ替え式は、データをページングするときに記憶されます

図 11: 並べ替え式は、データをページングするときに記憶されます (フルサイズの画像を表示する をクリックします)

手順 6: リピータ内のレコードを介したカスタム ページング

DataList の例では、非効率的な既定のページング手法を使用して、手順 5 ページでデータを調べました。 十分に大量のデータをページングする場合は、カスタム ページングを使用することが不可欠です。 「大量のデータを効率的にページングする」および「カスタム ページ データの並べ替え」チュートリアルに戻り、カスタム ページングとカスタム ページングの違いを調べ、カスタム ページングとカスタム ページ データの並べ替えを利用するために BLL でメソッドを作成しました。 特に、これら 2 つの前のチュートリアルでは、次の 3 つのメソッドを ProductsBLL クラスに追加しました。

  • GetProductsPaged(startRowIndex, maximumRows) は、 startRowIndex から始まり 、maximumRows を超えないレコードの特定のサブセットを返します。
  • GetProductsPagedAndSorted(sortExpression, startRowIndex, maximumRows) は、指定された sortExpression 入力パラメーターで並べ替えられたレコードの特定のサブセットを返します。
  • TotalNumberOfProducts() は、データベース テーブル内のレコードの合計数を Products 提供します。

これらのメソッドを使用すると、DataList コントロールまたは Repeater コントロールを使用してデータを効率的にページングおよび並べ替えることができます。 これを説明するために、まずカスタム ページングをサポートする Repeater コントロールを作成します。次に、並べ替え機能を追加します。

フォルダー内の SortingWithCustomPaging.aspx ページを PagingSortingDataListRepeater 開き、Repeater をページに追加し、そのプロパティを IDProducts設定します。 Repeater のスマート タグから、 という名前 ProductsDataSourceの新しい ObjectDataSource を作成します。 クラスの GetProductsPaged メソッドからProductsBLLデータを選択するように構成します。

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

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

[UPDATE]、[INSERT]、[DELETE] タブのドロップダウン リストを [(なし)] に設定し、[次へ] ボタンをクリックします。 データ ソースの構成ウィザードで、メソッドの startRowIndex および maximumRows 入力パラメーターのGetProductsPagedソースの入力を求めるメッセージ表示されるようになりました。 実際には、これらの入力パラメーターは無視されます。 代わりに、startRowIndexmaximumRows の値は、このチュートリアルの最初のデモで sortExpression を指定した方法と同様に、ObjectDataSource のSelectingイベント ハンドラーの プロパティを介してArguments渡されます。 そのため、ウィザードのパラメーター ソース ドロップダウン リストは [なし] のままにします。

[パラメーター ソース] を [なし] に設定したままにする

図 13: [パラメーター ソース] は [なし] のままにします (フルサイズの画像を表示する場合は、ここをクリックします)

注意

ObjectDataSource の EnablePaging プロパティを にtrue設定しないでください。 これにより、ObjectDataSource は、独自の startRowIndex パラメーターと maximumRows パラメーターを既存のパラメーター リストに自動的に SelectMethod 含めます。 このプロパティはEnablePaging、カスタム ページ データを GridView、DetailsView、または FormView コントロールにバインドする場合に便利です。これらのコントロールは、ObjectDataSource からの特定の動作を想定しているため、プロパティが のtrue場合EnablePagingにのみ使用できます。 DataList と Repeater のページング サポートを手動で追加する必要があるため、必要な機能を ASP.NET ページ内で直接ベイクするため、このプロパティ false は (既定値) のままにしておきます。

最後に、製品の名前、カテゴリ、サプライヤーが表示されるように Repeater ItemTemplate を定義します。 これらの変更後、Repeater と ObjectDataSource の宣言構文は次のようになります。

<asp:Repeater ID="Products" runat="server" DataSourceID="ProductsDataSource"
    EnableViewState="False">
    <ItemTemplate>
        <h4><asp:Label ID="ProductNameLabel" runat="server"
            Text='<%# Eval("ProductName") %>'></asp:Label></h4>
        Category:
        <asp:Label ID="CategoryNameLabel" runat="server"
            Text='<%# Eval("CategoryName") %>'></asp:Label><br />
        Supplier:
        <asp:Label ID="SupplierNameLabel" runat="server"
            Text='<%# Eval("SupplierName") %>'></asp:Label><br />
        <br />
        <br />
    </ItemTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProductsPaged" TypeName="ProductsBLL">
    <SelectParameters>
        <asp:Parameter Name="startRowIndex" Type="Int32" />
        <asp:Parameter Name="maximumRows" Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

少し時間を取ってブラウザーからページにアクセスし、レコードが返されていないことに注意してください。 これは、 startRowIndex パラメーター値と maximumRows パラメーター値をまだ指定していないためです。したがって、両方に対して 0 の値が渡されます。 これらの値を指定するには、ObjectDataSource の Selecting イベントのイベント ハンドラーを作成し、プログラムによってこれらのパラメーター値をそれぞれ 0 と 5 のハードコーディングされた値に設定します。

protected void ProductsDataSource_Selecting
    (object sender, ObjectDataSourceSelectingEventArgs e)
{
    e.InputParameters["startRowIndex"] = 0;
    e.InputParameters["maximumRows"] = 5;
}

この変更により、ブラウザーで表示されたページには、最初の 5 つの製品が表示されます。

最初の 5 つのレコードが表示される

図 14: 最初の 5 つのレコードが表示されます (フルサイズの画像を表示する場合はクリックします)

注意

図 14 に示されている製品は、効率的なカスタム ページング クエリを実行するストアド プロシージャによって結果が によって並べ替えられるため GetProductsPaged 、製品名で ProductName並べ替えられます。

ユーザーがページをステップ実行できるようにするには、開始行インデックスと最大行を追跡し、ポストバック間でこれらの値を記憶する必要があります。 既定のページングの例では、querystring フィールドを使用してこれらの値を保持しました。このデモでは、この情報をページのビューステートに保持してみましょう。 次の 2 つのプロパティを作成します。

private int StartRowIndex
{
    get
    {
        object o = ViewState["StartRowIndex"];
        if (o == null)
            return 0;
        else
            return (int)o;
    }
    set
    {
        ViewState["StartRowIndex"] = value;
    }
}
private int MaximumRows
{
    get
    {
        object o = ViewState["MaximumRows"];
        if (o == null)
            return 5;
        else
            return (int)o;
    }
    set
    {
        ViewState["MaximumRows"] = value;
    }
}

次に、Selecting イベント ハンドラーのコードを更新して、ハードコーディングされた値 0 と 5 の代わりに プロパティと MaximumRows プロパティを使用StartRowIndexするようにします。

e.InputParameters["startRowIndex"] = StartRowIndex;
e.InputParameters["maximumRows"] = MaximumRows;

この時点でも、ページには最初の 5 つのレコードだけが表示されます。 ただし、これらのプロパティが設定された状態で、ページング インターフェイスを作成する準備ができました。

ページング インターフェイスの追加

既定のページングの例で使用したのと同じ First、Previous、Next、Last ページング インターフェイスを使用してみましょう。たとえば、表示されているデータのページと合計ページ数を表示する Label Web コントロールを含みます。 Repeater の下に 4 つのボタン Web コントロールとラベルを追加します。

<p>
    <asp:Button runat="server" ID="FirstPage" Text="<< First" />
    <asp:Button runat="server" ID="PrevPage" Text="< Prev" />
    <asp:Button runat="server" ID="NextPage" Text="Next >" />
    <asp:Button runat="server" ID="LastPage" Text="Last >>" />
</p>
<p>
    <asp:Label runat="server" ID="CurrentPageNumber"></asp:Label>
</p>

次に、4 つのボタンのイベント ハンドラーを作成 Click します。 これらのボタンのいずれかがクリックされると、 を更新 StartRowIndex し、データを Repeater に再バインドする必要があります。 [最初]、[前へ]、[次へ] ボタンのコードは簡単ですが、[最後] ボタンの場合、データの最後のページの開始行インデックスを決定するにはどうすればよいですか? このインデックスを計算し、[次へ] ボタンと [最後] ボタンを有効にする必要があるかどうかを判断するには、合計でページングされているレコードの数を把握する必要があります。 これを確認するために、 クラスの メソッドTotalNumberOfProducts()ProductsBLL呼び出します。 メソッドの結果を返す という名前 TotalRowCount の読み取り専用のページ レベルのプロパティを TotalNumberOfProducts() 作成しましょう。

private int TotalRowCount
{
    get
    {
        // Return the value from the TotalNumberOfProducts() method
        ProductsBLL productsAPI = new ProductsBLL();
        return productsAPI.TotalNumberOfProducts();
    }
}

このプロパティを使用して、最後のページの開始行インデックスを決定できるようになりました。 具体的には、負の 1 の整数の結果を TotalRowCount で除算し MaximumRows、 に を乗算します MaximumRows。 4 つのページング インターフェイス ボタンのイベント ハンドラーを記述 Click できるようになりました。

protected void FirstPage_Click(object sender, EventArgs e)
{
    // Return to StartRowIndex of 0 and rebind data
    StartRowIndex = 0;
    Products.DataBind();
}
protected void PrevPage_Click(object sender, EventArgs e)
{
    // Subtract MaximumRows from StartRowIndex and rebind data
    StartRowIndex -= MaximumRows;
    Products.DataBind();
}
protected void NextPage_Click(object sender, EventArgs e)
{
    // Add MaximumRows to StartRowIndex and rebind data
    StartRowIndex += MaximumRows;
    Products.DataBind();
}
protected void LastPage_Click(object sender, EventArgs e)
{
    // Set StartRowIndex = to last page's starting row index and rebind data
    StartRowIndex = ((TotalRowCount - 1) / MaximumRows) * MaximumRows;
    Products.DataBind();
}

最後に、データの最初のページを表示する場合はページング インターフェイスの [最初] ボタンと [前へ] ボタン、最後のページを表示する場合は [次へ] ボタンと [最後へ] ボタンを無効にする必要があります。 これを実現するには、ObjectDataSource のイベント ハンドラーに次の Selecting コードを追加します。

// Disable the paging interface buttons, if needed
FirstPage.Enabled = StartRowIndex != 0;
PrevPage.Enabled = StartRowIndex != 0;
int LastPageStartRowIndex = ((TotalRowCount - 1) / MaximumRows) * MaximumRows;
NextPage.Enabled = StartRowIndex < LastPageStartRowIndex;
LastPage.Enabled = StartRowIndex < LastPageStartRowIndex;

これらの Click イベント ハンドラーと、現在の開始行インデックスに基づいてページング インターフェイス要素を有効または無効にするコードを追加した後、ブラウザーでページをテストします。 図 15 に示すように、最初にページにアクセスすると、[最初] ボタンと [前へ] ボタンが無効になります。 [次へ] をクリックすると 2 ページ目のデータが表示され、[最終ページ] をクリックすると最終ページが表示されます (図 16 および図 17 を参照)。 データの最後のページを表示すると、[次へ] ボタンと [最後へ] ボタンの両方が無効になります。

製品の最初のページを表示すると、[前] ボタンと [最後] ボタンが無効になる

図 15: 製品の最初のページを表示すると、[前] ボタンと [最後] ボタンが無効になります (フルサイズの画像を表示する場合をクリックします)

商品の2ページ目が表示されます。

図 16: 製品の 2 番目のページが表示されます (フルサイズの画像を表示する をクリックします)

[最後] をクリックすると、データの最終ページが表示されます

図 17: [最後] をクリックすると、データの最終ページが表示されます (クリックするとフルサイズの画像が表示されます)

手順 7: カスタム ページリピータを使用した並べ替えのサポートを含む

カスタム ページングが実装されたので、並べ替えのサポートを含める準備ができました。 クラス s GetProductsPagedAndSorted メソッドの startRowIndex および maximumRows 入力パラメーターGetProductsPagedProductsBLL と同じですが、追加の sortExpression 入力パラメーターを使用できます。 から SortingWithCustomPaging.aspxメソッドをGetProductsPagedAndSorted使用するには、次の手順を実行する必要があります。

  1. ObjectDataSource の プロパティを SelectMethod から GetProductsPagedGetProductsPagedAndSorted変更します。
  2. ObjectDataSource のSelectParametersコレクションに sortExpressionParameter オブジェクトを追加します。
  3. ページのビューステートを通じてポストバック間でその値を保持するプライベートなページレベル SortExpression のプロパティを作成します。
  4. ObjectDataSource の Selecting イベント ハンドラーを更新して、ObjectDataSource の sortExpression パラメーターにページ レベル SortExpression のプロパティの値を割り当てます。
  5. 並べ替えインターフェイスを作成します。

まず、ObjectDataSource の SelectMethod プロパティを更新し、sortExpression を追加しますParametersortExpressionParameterType プロパティが に設定されていることを確認しますString。 これらの最初の 2 つのタスクを完了すると、ObjectDataSource の宣言型マークアップは次のようになります。

<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}" TypeName="ProductsBLL"
    SelectMethod="GetProductsPagedAndSorted"
    OnSelecting="ProductsDataSource_Selecting">
    <SelectParameters>
        <asp:Parameter Name="sortExpression" Type="String" />
        <asp:Parameter Name="startRowIndex" Type="Int32" />
        <asp:Parameter Name="maximumRows" Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

次に、状態を表示するために値をシリアル化するページ レベル SortExpression のプロパティが必要です。 並べ替え式の値が設定されていない場合は、既定として ProductName を使用します。

private string SortExpression
{
    get
    {
        object o = ViewState["SortExpression"];
        if (o == null)
            return "ProductName";
        else
            return o.ToString();
    }
    set
    {
        ViewState["SortExpression"] = value;
    }
}

ObjectDataSource が メソッドを GetProductsPagedAndSorted 呼び出す前に、 sortExpressionParameter を プロパティの値に設定する SortExpression 必要があります。 イベント ハンドラーで Selecting 、次のコード行を追加します。

e.InputParameters["sortExpression"] = SortExpression;

残っているのは、並べ替えインターフェイスを実装することです。 前の例で行ったように、ユーザーが製品名、カテゴリ、またはサプライヤーで結果を並べ替えることを可能にする 3 つのボタン Web コントロールを使用して、並べ替えインターフェイスを実装してみましょう。

<asp:Button runat="server" id="SortByProductName"
    Text="Sort by Product Name" />
<asp:Button runat="server" id="SortByCategoryName"
    Text="Sort by Category" />
<asp:Button runat="server" id="SortBySupplierName"
    Text="Sort by Supplier" />

これら 3 つの Button コントロールのイベント ハンドラーを作成 Click します。 イベント ハンドラーで、 を StartRowIndex 0 にリセットし、 を SortExpression 適切な値に設定し、データを Repeater に再バインドします。

protected void SortByProductName_Click(object sender, EventArgs e)
{
    StartRowIndex = 0;
    SortExpression = "ProductName";
    Products.DataBind();
}
protected void SortByCategoryName_Click(object sender, EventArgs e)
{
    StartRowIndex = 0;
    SortExpression = "CategoryName";
    Products.DataBind();
}
protected void SortBySupplierName_Click(object sender, EventArgs e)
{
    StartRowIndex = 0;
    SortExpression = "CompanyName";
    Products.DataBind();
}

それがすべてです! カスタム ページングと並べ替えを実装するための手順は多数ありましたが、この手順は既定のページングに必要な手順とよく似ています。 図 18 は、カテゴリ別に並べ替えられたデータの最後のページを表示するときの製品を示しています。

カテゴリ別に並べ替えられたデータの最後のページが表示されます

図 18: [カテゴリ別に並べ替えられたデータの最後のページ] が表示されます (フルサイズの画像を表示する場合はクリックします)

注意

前の例では、仕入先 SupplierName による並べ替え時に、並べ替え式としてが使用されていました。 ただし、カスタム ページングの実装では、CompanyName を使用する必要があります。 これは、カスタム ページングを実装するストアド プロシージャが並べ替え式をGetProductsPagedAndSortedキーワード (keyword)にROW_NUMBER()渡すからです。キーワード (keyword)にはROW_NUMBER()、エイリアスではなく実際の列名が必要です。 したがって、並べ替え式のクエリ () でSuppliers使用される別名ではなく、SupplierName(テーブル内SELECTの列の名前) を使用CompanyNameする必要があります。

まとめ

DataList と Repeater はどちらも組み込みの並べ替えサポートを提供しませんが、コードとカスタム並べ替えインターフェイスを少し使用して、このような機能を追加できます。 並べ替えを実装するがページングを実装しない場合、並べ替え式は ObjectDataSource の Select メソッドに渡されるオブジェクトを通じてDataSourceSelectArguments指定できます。 この DataSourceSelectArguments オブジェクトの SortExpression プロパティは、ObjectDataSource の Selecting イベント ハンドラーで割り当てることができます。

ページングのサポートが既に提供されている DataList または Repeater に並べ替え機能を追加するには、並べ替え式を受け入れるメソッドを含むようにビジネス ロジック レイヤーをカスタマイズするのが最も簡単な方法です。 この情報は、ObjectDataSource の SelectParametersパラメーターを介して渡すことができます。

このチュートリアルでは、DataList コントロールと Repeater コントロールを使用したページングと並べ替えの調査を完了します。 次の最後のチュートリアルでは、項目ごとにユーザーが開始するカスタム機能を提供するために、DataList と Repeater のテンプレートに Button Web コントロールを追加する方法について説明します。

プログラミングに満足!

著者について

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

特別な感謝

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