DataList または Repeater コントロールのレポート データをページングする (VB)

作成者: Scott Mitchell

PDF のダウンロード

DataList でも Repeater でも自動のページングや並べ替えはサポートされていませんが、このチュートリアルでは DataList または Repeater にページングのサポートを追加する方法を説明します。これにより、はるかに柔軟性の高いページングとデータ表示インターフェイスが可能となります。

はじめに

ページングと並べ替えは、オンライン アプリケーションでデータを表示する場合の 2 つの非常に一般的な機能です。 たとえば、オンライン書店で ASP.NET に関する本を検索する場合、対象となる本は何百冊もある可能性があるとしても、検索結果リストを示すレポートには、1 ページあたり 10 件の一致データしか表示されません。 さらに、検索結果はタイトル、価格、ページ数、著者名などを基準に並べ替えることができます。 「レポート データのページングと並べ替え」のチュートリアルで説明したように、GridView、DetailsView、FormView の各コントロールはすべて、チェック ボックスにチェックを付けることで有効にできる組み込みのページング サポートを提供しています。 GridView には、並べ替えのサポートも含まれています。

残念ながら、DataList と Repeater ではどちらも、自動のページングまたは並べ替えのサポートは提供されていません。 このチュートリアルでは、DataList または Repeater にページングのサポートを追加する方法について詳しく取り上げます。 手動でページング インターフェイスを作成し、レコードの適切なページを表示し、ポストバック間でアクセスされたページを記憶する必要があります。 この場合、GridView、DetailsView、FormView を使用するよりも多くの時間とコードが必要ですが、DataList と Repeater を使用することで、はるかに柔軟性の高いページングとデータ表示インターフェイスが可能となります。

Note

このチュートリアルでは、ページングのみに焦点を当てます。 次のチュートリアルで、並べ替え機能の追加を取り上げます。

ステップ 1: ページングと並べ替えのチュートリアルの Web ページを追加する

今回のチュートリアルを開始する前に、まず、今回と次回のチュートリアルで必要になる ASP.NET ページを追加しましょう。 まず、プロジェクトに PagingSortingDataListRepeater という名前で新しいフォルダーを作成します。 次に、以下の 5 つの ASP.NET ページをこのフォルダーに追加します。そのすべてをマスター ページ Site.master を使用するように構成します。

  • Default.aspx
  • Paging.aspx
  • Sorting.aspx
  • SortingWithDefaultPaging.aspx
  • SortingWithCustomPaging.aspx

Create a PagingSortingDataListRepeater Folder and Add the Tutorial ASP.NET Pages

図 1: PagingSortingDataListRepeater フォルダーを作成し、チュートリアルの ASP.NET ページを追加する

次に、Default.aspx ページを開き、UserControls フォルダーの SectionLevelTutorialListing.ascx ユーザー コントロールをデザイン画面にドラッグします。 「マスター ページとサイト ナビゲーション」のチュートリアルで作成したこのユーザー コントロールは、サイト マップを列挙し、そこにあるチュートリアルを現在のセクションに箇条書きで表示します。

Add the SectionLevelTutorialListing.ascx User Control to Default.aspx

図 2: SectionLevelTutorialListing.ascx ユーザー コントロールを Default.aspx に追加する (クリックするとフルサイズの画像が示されます)

作成するページングと並べ替えのチュートリアルを箇条書きに表示するには、それをサイト マップに追加する必要があります。 Web.sitemap ファイルを開き、「Editing and Deleting with the DataList」のサイト マップ ノードのマークアップの後に、次のマークアップを追加します。

<siteMapNode
    url="~/PagingSortingDataListRepeater/Default.aspx"
    title="Paging and Sorting with the DataList and Repeater"
    description="Paging and Sorting the Data in the DataList and Repeater Controls">
    <siteMapNode
        url="~/PagingSortingDataListRepeater/Paging.aspx"
        title="Paging"
        description="Learn how to page through the data shown
                     in the DataList and Repeater controls." />
    <siteMapNode
        url="~/PagingSortingDataListRepeater/Sorting.aspx"
        title="Sorting"
        description="Sort the data displayed in a DataList or
                     Repeater control." />
    <siteMapNode
        url="~/PagingSortingDataListRepeater/SortingWithDefaultPaging.aspx"
        title="Sorting with Default Paging"
        description="Create a DataList or Repeater control that is paged using
                     default paging and can be sorted." />
    <siteMapNode
        url="~/PagingSortingDataListRepeater/SortingWithCustomPaging.aspx"
        title="Sorting with Custom Paging"
        description="Learn how to sort the data displayed in a DataList or
                     Repeater control that uses custom paging." />
</siteMapNode>

Update the Site Map to Include the New ASP.NET Pages

図 3: 新しい ASP.NET ページが含まれるようにサイト マップを更新する

ページングのレビュー

前のチュートリアルでは、GridView、DetailsView、FormView の各コントロールでデータをページングする方法について確認しました。 この 3 つのコントロールでは、コントロールのスマート タグで [ページングを有効にする] オプションをチェックするだけで実装できる、"既定のページング" と呼ばれる単純な形式のページングが提供されます。 既定のページングでは、最初のページへのアクセス、またはユーザーが別のデータのページに移動したときに、データのページが要求されるたびに、GridView、DetailsView、FormView の各コントロールが ObjectDataSource から "すべて" のデータを再要求します。 その後、要求されたページ インデックスと、ページあたりの表示レコード数を踏まえて、表示する特定のレコード セットを切り取ります。 既定のページングについては、「レポート データのページングと並べ替え」のチュートリアルで詳しく説明しています。

既定のページングでは、ページごとにすべてのレコードが再要求されるため、大量のデータをページングする場合は実用的ではありません。 たとえば、10 件のページ サイズで 50,000 件のレコードをページングするとします。 ユーザーが新しいページに移動するたびに、50,000 件のレコードがすべてデータベースから取得されることになりますが、表示されるのは、そのうちの 10 件だけです。

"カスタム ページング" では、要求されたページに表示するレコードの正確なサブセットのみを取得することで、既定のページングのパフォーマンスに関する問題が解決されます。 カスタム ページングを実装する場合は、正確なレコード セットだけを効率的に返す SQL クエリを記述する必要があります。 そのようなクエリを SQL Server 2005 の新しい ROW_NUMBER() keyword を使用して作成する方法については、以前に「大量のデータを効率的にページングする」のチュートリアルで確認しました。

DataList コントロールまたは Repeater コントロールに既定のページングを実装するために、PagedDataSource class を、ページングされるコンテンツを持つ ProductsDataTable のラッパーとして使用できます。 この PagedDataSource クラスには、列挙可能なオブジェクトに割り当てることができる DataSource プロパティと、ページあたりの表示レコード数と現在のページ インデックスを示す PageSizeCurrentPageIndex のプロパティがあります。 これらのプロパティを設定すると、PagedDataSource を任意のデータ Web コントロールのデータ ソースとして利用できます。 列挙時に、PagedDataSourcePageSizeCurrentPageIndex のプロパティに基づいて、内部の DataSource の適切なレコードのサブセットのみを返します。 図 4 は、PagedDataSource クラスの機能を示しています。

The PagedDataSource Wraps an Enumerable Object with a Pageable Interface

図 4: PagedDataSource はページング可能なインターフェイスで列挙可能なオブジェクトをラップする

PagedDataSource オブジェクトは、ビジネス ロジック レイヤーから直接作成し構成して、ObjectDataSource を用いて DataList または Repeater にバインドすることができます。または、ASP.NET ページの分離コード クラスで直接作成し構成することもできます。 後者の方法を使用する場合は、ObjectDataSource の使用を控え、代わりに、ページングされたデータを DataList または Repeater にプログラムによってバインドする必要があります。

PagedDataSource オブジェクトには、カスタム ページングをサポートするプロパティもあります。 ただし、カスタム ページング向けに設計された、表示する正確なレコードを返す ProductsBLL クラスの BLL メソッドが既に存在するため、カスタム ページングでは PagedDataSource の使用をバイパスできます。

このチュートリアルでは、適切に構成された PagedDataSource オブジェクトを返す ProductsBLL クラスに新しいメソッドを追加することで、DataList に既定のページングを実装する方法について取り上げます。 次のチュートリアルでは、カスタム ページングの使用方法を確認していきます。

ステップ 2: ビジネス ロジック レイヤーに既定のページング メソッドを追加する

この ProductsBLL クラスには現在、すべての製品情報を返すメソッド GetProducts() と、開始インデックスで製品の特定のサブセットを返すメソッド GetProductsPaged(startRowIndex, maximumRows) があります。 既定のページングでは、GridView、DetailsView、FormView の各コントロールはすべて、GetProducts() メソッドを使用してすべての製品を取得しますが、内部的に PagedDataSource を使用してレコードの正しいサブセットのみを表示します。 DataList コントロールと Repeater コントロールで、この機能を再現するには、この動作を模倣する新しいメソッドを BLL に作成します。

次の 2 つの整数入力パラメーターを受け取る GetProductsAsPagedDataSource という名前の ProductsBLL クラスにメソッドを追加します。

  • pageIndex 表示するページのインデックス、インデックス位置 0
  • pageSize ページあたりの表示レコード数。

GetProductsAsPagedDataSource はまず、GetProducts() から "すべて" のレコードを取得します。 次に、PagedDataSource オブジェクトを作成し、その CurrentPageIndexPageSize のプロパティを、渡された pageIndexpageSize のパラメーターの値に設定します。 このメソッドは、次の構成の PagedDataSource を返して終了します。

<System.ComponentModel.DataObjectMethodAttribute _
    (System.ComponentModel.DataObjectMethodType.Select, False)> _
Public Function GetProductsAsPagedDataSource(ByVal pageIndex As Integer, _
    ByVal pageSize As Integer) As PagedDataSource
    ' Get ALL of the products
    Dim products As Northwind.ProductsDataTable = GetProducts()
    ' Limit the results through a PagedDataSource
    Dim pagedData As New PagedDataSource()
    pagedData.DataSource = products.Rows
    pagedData.AllowPaging = True
    pagedData.CurrentPageIndex = pageIndex
    pagedData.PageSize = pageSize
    Return pagedData
End Function

ステップ 3: 既定のページングを使用して DataList で製品情報を表示する

ProductsBLL クラスに GetProductsAsPagedDataSource メソッドを追加したことで、既定のページングを提供する DataList または Repeater を作成できるようになりました。 まず、PagingSortingDataListRepeater フォルダー内のPaging.aspx ページを開き、ツールボックスから DataList を Designer にドラッグして、DataList の ID プロパティを ProductsDefaultPaging に設定します。 DataList のスマート タグから、ProductsDefaultPagingDataSource という名前で新しい ObjectDataSource を作成し、GetProductsAsPagedDataSource メソッドを使用してデータを取得するようにそれを構成します。

Create an ObjectDataSource and Configure it to Use the GetProductsAsPagedDataSource () Method

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

[UPDATE]、[INSERT]、[DELETE] の各タブのドロップダウン リストを (None) に設定します。

Set the Drop-Down Lists in the UPDATE, INSERT, and DELETE tabs to (None)

図 6: [UPDATE]、[INSERT]、[DELETE] の各タブのドロップダウン リストを (None) に設定する (クリックするとフルサイズの画像が表示されます)

GetProductsAsPagedDataSource メソッドは 2 つの入力パラメーターを必要とするため、ウィザードによってこれらのパラメーター値のソースを入力するよう求められます。

ページ インデックスとページ サイズの値は、ポストバック間で記憶される必要があります。 それらはビュー状態での保存、クエリ文字列での保持、セッション変数への格納のほか、他のいくつかの手法を使用して記憶させることができます。 このチュートリアルでは、データの特定のページをブックマークできるという利点があるクエリ文字列を使用します。

具体的には、クエリ文字列フィールドの pageIndex と pageSize をそれぞれ pageIndexpageSize のパラメーターに使用します (図 7 を参照)。 ユーザーがこのページに初めてアクセスするときにはクエリ文字列の値が存在しないため、これらのパラメーターの既定値の設定には少し時間がかかります。 pageIndex の既定値を 0 (データの最初のページが表示されます) に、pageSize の既定値を 4 に設定します。

Use the QueryString as the Source for the pageIndex and pageSize Parameters

図 7: クエリ文字列を pageIndexpageSize のパラメーターのソースとして使用する (クリックするとフルサイズの画像が表示されます)

ObjectDataSource を構成すると、Visual Studio によって DataList の ItemTemplate が自動的に作成されます。 製品名、カテゴリ、サプライヤーのみが表示されるように ItemTemplate をカスタマイズします。 また、DataList の RepeatColumns プロパティを 2 に、その Width を 100% に、ItemStyleWidth を 50% に設定します。 これらの幅の設定により、2 つの列の間隔が等しくなります。

これらの変更を行った後の DataList と ObjectDataSource のマークアップは次のようになります。

<asp:DataList ID="ProductsDefaultPaging" runat="server" Width="100%"
    DataKeyField="ProductID" DataSourceID="ProductsDefaultPagingDataSource"
    RepeatColumns="2" 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>
    <ItemStyle Width="50%" />
</asp:DataList>
<asp:ObjectDataSource ID="ProductsDefaultPagingDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}" TypeName="ProductsBLL"
    SelectMethod="GetProductsAsPagedDataSource">
    <SelectParameters>
        <asp:QueryStringParameter DefaultValue="0" Name="pageIndex"
             QueryStringField="pageIndex" Type="Int32" />
        <asp:QueryStringParameter DefaultValue="4" Name="pageSize"
             QueryStringField="pageSize" Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

Note

このチュートリアルでは更新や削除の機能を実行していないため、DataList のビュー状態を無効にして、レンダリングされるページ サイズを小さくできます。

ブラウザーからこのページに最初にアクセスするときには、pageIndexpageSize のクエリ文字列パラメーターはどちらも指定されません。 そのため、既定値の 0 と 4 が使用されます。 図 8 に示すように、これは、最初の 4 つの製品を表示する DataList になります。

The First Four Products are Listed

図 8: 最初の 4 つの製品の一覧が表示される (クリックするとフルサイズの画像が表示されます)

ページング インターフェイスがないので、今のところユーザーにとって、データの 2 ページ目に移動する簡単な手段はありません。 ステップ 4 でページング インターフェイスを作成します。 現時点では、クエリ文字列でページング条件を直接指定することによってのみページングを実行できます。 たとえば、2 ページ目を表示するには、ブラウザーのアドレス バーの URL を Paging.aspx から Paging.aspx?pageIndex=2 に変更して Enter キーを押します。 これにより、データの 2 ページ目が表示されます (図 9 を参照)。

Screenshot of the Paging Data in a DataList window showing the second page of data.

図 9: データの 2 ページ目が表示される (クリックするとフルサイズの画像が表示されます)

ステップ 4: ページング インターフェイスを作成する

実装できるページング インターフェイスにはさまざまなものがあります。 GridView、DetailsView、FormView の各コントロールには、次の 4 つの異なるインターフェイスが用意されていて、この中から選択できます。

  • [次へ]、[前へ] ユーザーは一度に 1 ページずつ、次のページか前のページに移動できます。
  • [次へ]、[前へ]、[最初へ]、[最後へ][次へ] と [前へ] のボタンに加えて、このインターフェイスには、先頭ページまたは最終ページに移動するための [最初へ] と [最後へ] のボタンが含まれています。
  • 数値ページング インターフェイスにページ番号が一覧表示され、ユーザーが特定のページにすばやく移動できます。
  • 数値、[最初へ]、[最後へ]数値によるページ番号に加えて、先頭ページまたは最終ページに移動するためのボタンが含まれています。

DataList と Repeater の場合には、ページング インターフェイスを決定し実装する必要があります。 これには、ページに必要な Web コントロールを作成することと、特定のページング インターフェイス ボタンがクリックされたときに、要求されたページを表示することが含まれています。 さらに、特定のページング インターフェイス制御を無効にしなければならない場合があります。 たとえば、"[次へ]、[前へ]、[最初へ]、[最後へ]" のインターフェイスを使用してデータの最初のページを表示している時は、[最初へ] と [前へ] の両ボタンを無効にします。

このチュートリアルでは、"[次へ]、[前へ]、[最初へ]、[最後へ]" のインターフェイスを使用します。 4 つのボタン Web コントロールをページに追加し、その IDFirstPagePrevPageNextPageLastPage に設定します。 Text プロパティを << 最初へ、< 前へ、次へ >、最後へ >> に設定します。

<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 >>" />

次に、これらの各ボタンごとに Click イベント ハンドラーを作成します。 すぐに、要求されたページを表示するために必要なコードを追加します。

ページング対象レコードの合計数を記憶する

どのページング インターフェイスを選択しても、ページング対象レコードの合計数を計算して記憶する必要があります。 合計行数によって (ページ サイズと組み合わせて)、ページングされるデータの合計ページ数が決まります。これにより、どのページング インターフェイス制御を追加または有効にするかを特定できます。 ここで構築する "[次へ]、[前へ]、[最初へ]、[最後へ]" のインターフェイスでは、ページ数を次の 2 つの状況で利用します。

  • 最後のページを表示しているかどうかを判断するために。この場合、[次へ] と [最後へ] のボタンが無効になります。
  • ユーザーが [最後へ] ボタンをクリックした場合、最後のページ (インデックスがページ数より 1 つ小さい) に移動する必要があります。

ページ数は、合計行数をページ サイズで割った値を切り上げた数値として計算されます。 たとえば、ページあたり 4 つのレコードとして 79 件のレコードをページングする場合、ページ数は 20 になります (79 / 4 の切り上げ)。 数値ページング インターフェイスを使用している場合は、この情報によって、表示すべき数値ページ ボタンの数がわかります。ページング インターフェイスに [次へ] または [最後へ] ボタンが含まれている場合は、ページ数は [次へ] または [最後へ] ボタンを無効にするタイミングを決定するために使用されます。

ページング インターフェイスに [最後へ] ボタンが含まれている場合は、 [最後へ] ボタンがクリックされたときに最終ページのインデックスを判断できるように、ポストバック間でページング対象レコードの合計数が記憶されていることが不可欠です。 これを容易にするために、ASP.NET ページの分離コード クラスに、その値をビュー状態に保持する TotalRowCount プロパティを作成します。

Private Property TotalRowCount() As Integer
    Get
        Dim o As Object = ViewState("TotalRowCount")
        If (o Is Nothing) Then
            Return -1
        Else
            Return Convert.ToInt32(o)
        End If
    End Get
    set(Value as Integer)
        ViewState("TotalRowCount") = value
    End Set
End Property

TotalRowCount に加えて、ページ インデックス、ページ サイズ、ページ数に簡単にアクセスできるように、時間を取って、読み取り専用のページ レベルのプロパティを作成します。

Private ReadOnly Property PageIndex() As Integer
    Get
        If (Not String.IsNullOrEmpty(Request.QueryString("pageIndex"))) Then
            Return Convert.ToInt32(Request.QueryString("pageIndex"))
        Else
            Return 0
        End If
    End Get
End Property
Private ReadOnly Property PageSize() As Integer
    Get
        If (Not String.IsNullOrEmpty(Request.QueryString("pageSize"))) Then
            Return Convert.ToInt32(Request.QueryString("pageSize"))
        Else
            Return 4
        End If
    End Get
End Property
Private ReadOnly Property PageCount() As Integer
    Get
        If TotalRowCount <= 0 OrElse PageSize <= 0 Then
            Return 1
        Else
            Return ((TotalRowCount + PageSize) - 1) / PageSize
        End If
    End Get
End Property

ページング対象レコードの合計数を特定する

DataList に表示されるのは一部のサブセットだけだとしても、ObjectDataSource の Select() メソッドから返される PagedDataSource オブジェクトには、その中に "すべて" の製品レコードが含まれています。 PagedDataSourceCount property は DataList に表示される項目数のみを返します。DataSourceCount propertyPagedDataSource 内の項目の合計数を返します。 したがって、ASP.NET ページの TotalRowCount プロパティに PagedDataSourceDataSourceCount プロパティの値を割り当てる必要があります。

これを実現するには、ObjectDataSource の Selected イベントのイベント ハンドラーを作成します。 Selected イベント ハンドラーで、ObjectDataSource の Select() メソッドの戻り値、この場合は PagedDataSource にアクセスできます。

Protected Sub ProductsDefaultPagingDataSource_Selected(ByVal sender As Object, _
    ByVal e As System.Web.UI.WebControls.ObjectDataSourceStatusEventArgs) _
    Handles ProductsDefaultPagingDataSource.Selected
    ' Reference the PagedDataSource bound to the DataList
    Dim pagedData As PagedDataSource = CType(e.ReturnValue, PagedDataSource)
    ' Remember the total number of records being paged through across postbacks
    TotalRowCount = pagedData.DataSourceCount
End Sub

データの要求されたページを表示する

ユーザーがページング インターフェイスのいずれかのボタンをクリックすると、データの要求されたページを表示する必要があります。 ページング パラメーターはクエリ文字列を使用して指定されるため、データの要求されたページを表示するには、Response.Redirect(url) を使用して、適切なページング パラメーターを持つ Paging.aspx ページをユーザーのブラウザーに再要求させます。 たとえば、データの 2 ページ目を表示するには、ユーザーを Paging.aspx?pageIndex=1 にリダイレクトします。

これを容易にするために、ユーザーを Paging.aspx?pageIndex=sendUserToPageIndex にリダイレクトする RedirectUser(sendUserToPageIndex) メソッドを作成します。 次に、4 つの Button Click イベント ハンドラーからこのメソッドを呼び出します。 たとえば、FirstPageClick イベント ハンドラーでは、RedirectUser(0) を呼び出して、最初のページに送信し、PrevPageClick イベント ハンドラーでは、PageIndex - 1 をページ インデックスとして使用するなどです。

Protected Sub FirstPage_Click(ByVal sender As Object, ByVal e As EventArgs) _
    Handles FirstPage.Click
    ' Send the user to the first page
    RedirectUser(0)
End Sub
Protected Sub PrevPage_Click(ByVal sender As Object, ByVal e As EventArgs) _
    Handles PrevPage.Click
    ' Send the user to the previous page
    RedirectUser(PageIndex - 1)
End Sub
Protected Sub NextPage_Click(ByVal sender As Object, ByVal e As EventArgs) _
    Handles NextPage.Click
    ' Send the user to the next page
    RedirectUser(PageIndex + 1)
End Sub
Protected Sub LastPage_Click(ByVal sender As Object, ByVal e As EventArgs) _
    Handles LastPage.Click
    ' Send the user to the last page
    RedirectUser(PageCount - 1)
End Sub
Private Sub RedirectUser(ByVal sendUserToPageIndex As Integer)
    ' Send the user to the requested page
    Response.Redirect(String.Format("Paging.aspx?pageIndex={0}&pageSize={1}", _
        sendUserToPageIndex, PageSize))
End Sub

Click イベント ハンドラーが完了したら、ボタンをクリックして DataList のレコードをページングできます。 どうぞお試しください。

ページング インターフェイス制御を無効にする

現時点では、どのページが表示されていても、4 つのボタンはすべて有効になっています。 ただし、データの最初のページを表示している場合は [最初へ] と [前へ] のボタンを無効にし、最後のページを表示している場合は [次へ] と [最後へ] のボタンを無効にすることが必要です。 ObjectDataSource の Select() メソッドによって返される PagedDataSource オブジェクトには IsFirstPageIsLastPage のプロパティがあり、データの最初のページまたは最後のページを表示しているかどうかを調べて判断することができます。

ObjectDataSource の Selected イベント ハンドラーに次のコードを追加します。

' Configure the paging interface based on the data in the PagedDataSource
FirstPage.Enabled = Not pagedData.IsFirstPage
PrevPage.Enabled = Not pagedData.IsFirstPage
NextPage.Enabled = Not pagedData.IsLastPage
LastPage.Enabled = Not pagedData.IsLastPage

この追加により、最初のページを表示している時には [最初へ] と [前へ] のボタンが無効になり、最後のページを表示している時には [次へ] と [最後へ] のボタンが無効になります。

現在表示しているページと合計ページ数をユーザーに通知することで、ページング インターフェイスを完成させましょう。 Label Web コントロールをページに追加し、その ID プロパティを CurrentPageNumber に設定します。 ObjectDataSource の Selected イベント ハンドラーでその Text プロパティを、現在表示されているページ (PageIndex + 1) とページの合計数 (PageCount) が含まれるように設定します。

' Display the current page being viewed...
CurrentPageNumber.Text = String.Format("You are viewing page {0} of {1}...", _
    PageIndex + 1, PageCount)

図 10 は、最初にアクセスした時の Paging.aspx を示しています。 クエリ文字列は空であるため、DataList はデフォルトで最初の 4 つの製品を表示します。[最初へ] と [前へ] のボタンは無効になっています。 [次へ] をクリックすると、次の 4 つのレコードが表示されます (図 11 を参照)。[最初へ] と [前へ] のボタンが有効になりました。

The First Page of Data is Displayed

図 10: データの最初のページが表示されています (クリックするとフルサイズの画像が表示されます)

Screenshot displaying page 2 of the Paging Data in a DataList window.

図 11: データの 2 ページ目が表示されています (クリックするとフルサイズの画像が表示されます)

Note

ユーザーがページごとに表示するページ数を指定できるようにすることで、ページング インターフェイスをさらに強化できます。 たとえば、DropDownList には、5、10、25、50、All などのページ サイズ オプションの一覧を追加できます。 ページ サイズを選択すると、ユーザーは Paging.aspx?pageIndex=0&pageSize=selectedPageSize にリダイレクトされる必要があります。 この機能強化の実装については、皆さんの演習として残しておきます。

カスタム ページングを使用する

DataList では、効率的ではない既定のページング手法を使用してデータがページングされます。 大量のデータをページングする場合には、カスタム ページングを使用することが不可欠となります。 実装の詳細は若干異なりますが、DataList でカスタム ページングを実装する場合の背後にある概念は、既定のページングの場合と同じです。 カスタム ページングでは、ProductBLL クラス の GetProductsPaged メソッドを使用します (GetProductsAsPagedDataSource の代わりに)。 「大量のデータを効率的にページングする」のチュートリアルで説明したように、GetProductsPaged には開始行インデックスと返される行の最大数を渡す必要があります。 これらのパラメーターは、既定のページングで使用される pageIndexpageSize のパラメーターのように、クエリ文字列を使用して保持できます。

カスタム ページングには PagedDataSource がないため、別の手法を使用して、ページング対象レコードの合計数、およびデータの最初のページまたは最後のページを表示しているかどうかを判断する必要があります。 ProductsBLL クラスの TotalNumberOfProducts() メソッドは、ページングされる製品の合計数を返します。 データの最初のページが表示されているかどうかを判断するには、開始行インデックスを調べます。それが 0 の場合、最初のページが表示されています。 開始行インデックスと返される最大行数の合計が、ページング対象レコードの合計数以上の場合、最後のページが表示されています。

次のチュートリアルでは、カスタム ページングの実装について詳しく説明していきます。

まとめ

DataList コントロールと Repeater コントロールでは、GridView、DetailsView、FormView の各コントロールにみられるような、すぐに利用できるページング のサポートは提供されていませんが、このような機能はごく簡単に追加できます。 既定のページングの最も簡単な実装方法は、製品のセット全体を PagedDataSource 内にラップし、PagedDataSource を DataList または Repeater にバインドすることです。 このチュートリアルでは、PagedDataSource を返すように、GetProductsAsPagedDataSource メソッドを ProductsBLL クラスに追加しました。 この ProductsBLL クラスには既に、カスタム ページングに必要な GetProductsPagedTotalNumberOfProducts のメソッドが含まれています。

カスタム ページングで表示する正確なレコードセットを取得すること、または既定のページングで PagedDataSource のすべてのレコードを取得することと併せて、ページング インターフェイスを手動で追加することも必要です。 このチュートリアルでは、4 つのボタン Web コントロールを持つ "[次へ]、[前へ]、[最初へ]、[最後へ]" のインターフェイスを作成しました。 また、現在のページ番号と合計ページ数を表示する Label コントロールも追加しました。

次のチュートリアルでは、DataList と Repeater に並べ替えのサポートを追加する方法を確認していきます。 また、ページングと並べ替えの両方が可能な DataList を作成する方法についても説明していきます (既定のページングとカスタム ページングを使用した例を用いて)。

プログラミングに満足!

著者について

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

特別な感謝

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