QA@IT

GridViewのPagerTemplateの設定に関して

5299 PV

開発環境:ASP.NET(VS2010 C#.NET .NETFramework4.0)

いつもお世話になっております。

現在、GridViewののPagerに総レコード数と前ページ/後ろページと最大5ページ分のページ指定を設定したいと思っています。
PagerTemplateに下記のように設定しました。
※記載内容をそのまま表示する方法が分からなかったため、先頭の"<"を消去してます。
PagerTemplate>
asp:Label ID="lblSumCount" runat="server" Text = "該当件数○○件">/asp:Label
asp:LinkButton ID="LinkButtonP" runat="server" CommandName="Page" CommandArgument="Prev">前/asp:LinkButton
asp:LinkButton ID="LinkButton1" runat="server" CommandName="Page" CommandArgument="1">1/asp:LinkButton
asp:LinkButton ID="LinkButton2" runat="server" CommandName="Page" CommandArgument="2">2/asp:LinkButton
asp:LinkButton ID="LinkButton3" runat="server" CommandName="Page" CommandArgument="3">3/asp:LinkButton
asp:LinkButton ID="LinkButton4" runat="server" CommandName="Page" CommandArgument="4">4/asp:LinkButton
asp:LinkButton ID="LinkButton5" runat="server" CommandName="Page" CommandArgument="5">5/asp:LinkButton
asp:LinkButton ID="LinkButtonB" runat="server" CommandName="Page" CommandArgument="Next">次/asp:LinkButton>
/PagerTemplate>

総レコード数の表示やPageSizeに合うようにページボタンの制御をしたいのですが、
ただ、上記のようにPagerTemplateに記載するだけでは何一つできません。

どのように記載したら、総数を表示したりできますか。

回答

先の回答で「GridView でも同様なことができたかどうかは、ちょっと記憶にありません。思い出したら連絡します」と書きましたが、思い出したのでその方法を書いておきます。

Pagerに総レコード数と前ページ/後ろページと最大5ページ分のページ指定

先に紹介した ListView + DataPager を使う方法に較べてあまりスマートとは言えませんが、以下のような方法があります。

データーソースコントロール(SqlDataSource または ObjectDataSource)と GridView を組み合わせて使うことになると思いますが、その場合に「総レコード数」を取得するには、データーソースコントロールの Selected イベントのハンドラを使うのがよさそうです。

例えば、SqlDataSource を使う場合、その Selected イベントのハンドラの引数 SqlDataSourceStatusEventArgs の AffectedRows プロパティから「総レコード数」を取得できます。

取得した「総レコード数」をページャーの中に表示するのであれば、GridView.RowDataBound イベントのハンドラでページャーの行を探して、その中に追加します。

「前ページ/後ろページと最大5ページ分のページ指定」というのは、PagerSettings クラスを使って Mode プロパティを NumericFirstLast に設定するのが求める形に一番近くなると思います。

ご参考に、SqlDataSource + GridView の場合に、上記を実現するためのサンプルをアップしておきます。

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    int GridView3TotalCount = 0;

    protected void SqlDataSource1_Selected(
        object sender, SqlDataSourceStatusEventArgs e)
    {
        GridView3TotalCount = e.AffectedRows;
    }

    protected void GridView3_RowDataBound(
        object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.Pager)
        {
            Label label = new Label();
            label.Text = "総レコード数: " + GridView3TotalCount.ToString();
            e.Row.Cells[0].Controls.AddAt(0, label);
        }
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>GridView Total Records</title>
</head>
<body>
    <form id="form1" runat="server">
        <h1>GridView Total Records</h1>

        <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
            ConnectionString="<%$ ConnectionStrings:Northwind %>" 
            SelectCommand="SELECT * FROM [Orders]" 
            OnSelected="SqlDataSource1_Selected">
        </asp:SqlDataSource>

        <asp:GridView ID="GridView3" runat="server" AllowPaging="True" 
            AutoGenerateColumns="False" DataKeyNames="OrderID" 
            DataSourceID="SqlDataSource1" 
            OnRowDataBound="GridView3_RowDataBound">
            <PagerSettings Mode="NumericFirstLast" PageButtonCount="5" />
            <Columns>
                <asp:BoundField DataField="OrderID" 
                    HeaderText="OrderID" InsertVisible="False" 
                    ReadOnly="True" SortExpression="OrderID" />
                ・・・中略・・・
            </Columns>
        </asp:GridView>
    </form>
</body>
</html>

ObjectDataSource + GridView を使う場合も、ObjectDataSource.Selected イベントのハンドラで「総レコード数」を取得できます。

ObjectDataSource を使う場合、ページを切り替えるたびに全レコードを DB から再度取得するという無駄なことを避けるため、普通は、以下のページに書いてあるように、必要なレコードのみ DB から取得するクラス/メソッドを実装して、それらを ObjectDataSource で定義されているプロパティに設定することになると思います。

ObjectDataSource でページング
http://surferonwww.info/BlogEngine/post/2010/08/26/Paging-with-ObjectDataSource.aspx

上記のページのサンプルコードでは、GetDataByIndex と GetNumberOfMessages の 2 つのメソッドが ObjectDataSource に設定されていますが、その両方が呼ばれ、それぞれで Selected イベントが発生します(2 回 Selected イベントが発生します)。

その際、イベントハンドラの引数 ObjectDataSourceStatusEventArgs の ReturnValue プロパティでそれぞれのメソッドが返すオブジェクトを取得できます。

したがって、e.ReturnValue が Int32 型にキャストできれば GetNumberOfMessages が返したもの、即ち全レコード数ということになります。イベントハンドラのコードは以下のような感じになります。

protected void ObjectDataSource1_Selected(object sender, 
                              ObjectDataSourceStatusEventArgs e)
{
    if (e.ReturnValue is Int32)
    {
        GridView3TotalCount = (Int32)e.ReturnValue;
    }
}
編集 履歴 (1)
  • こんにちは。
    確認遅くなりましたが、参考にさせて貰ってなんとかできました。
    まだ、できましたレベルなのでもう少し勉強して自分のものにしたいと思います。
    -

遅ればせながら
こんな感じじゃダメかな?

            <PagerTemplate>
                <asp:ImageButton ID="ImageButton1" runat="server" ImageUrl="~/images/first.png" 
                    CommandArgument="First" CommandName="Page" OnCommand="Paginate" />
                <asp:ImageButton ID="ImageButton2" runat="server" ImageUrl="~/images/previous.png"
                    CommandArgument="Prev" CommandName="Page" OnCommand="Paginate" />
                Page
                <asp:DropDownList ID="ddlPages" runat="server" AutoPostBack="True" 
                    onselectedindexchanged="ddlPages_SelectedIndexChanged">
                </asp:DropDownList> of <asp:Label ID="lblPageCount" runat="server"></asp:Label>
                <asp:ImageButton ID="ImageButton3" runat="server" ImageUrl="~/images/next.png"
                    CommandArgument="Nex" CommandName="Page" OnCommand="Paginate" />
                <asp:ImageButton ID="ImageButton4" runat="server" ImageUrl="~/images/last.png"
                    CommandArgument="Last" CommandName="Page" OnCommand="Paginate" />
            </PagerTemplate>

    Private Sub GridView1_DataBound(sender As Object, e As System.EventArgs) Handles GridView1.DataBound

        Dim gvrPager As GridViewRow = GridView1.BottomPagerRow

        If gvrPager Is Nothing Then Return

        Dim ddlPages As DropDownList = CType(gvrPager.Cells(0).FindControl("ddlPages"), DropDownList)
        Dim lblPageCount As Label = CType(gvrPager.Cells(0).FindControl("lblPageCount"), Label)

        If ddlPages IsNot Nothing Then

            For i As Integer = 0 To GridView1.PageCount - 1

                Dim intPageNumber As Integer = i + 1

                Dim lstItem As ListItem = New ListItem(intPageNumber.ToString())
                If i = GridView1.PageIndex Then
                    lstItem.Selected = True

                End If

                ddlPages.Items.Add(lstItem)

            Next

        End If

        If lblPageCount IsNot Nothing Then

            lblPageCount.Text = GridView1.PageCount.ToString()

        End If

    End Sub

    Protected Sub ddlPages_SelectedIndexChanged(sender As Object, e As EventArgs)

        Dim gvrPager As GridViewRow = GridView1.BottomPagerRow
        Dim ddlPages As DropDownList = CType(gvrPager.Cells(0).FindControl("ddlPages"), DropDownList)

        GridView1.PageIndex = ddlPages.SelectedIndex

    End Sub

    Protected Sub Paginate(sender As Object, e As CommandEventArgs)

        Dim intCurIndex As Integer = GridView1.PageIndex

        Select Case e.CommandArgument.ToString.ToLower
            Case "first"
                GridView1.PageIndex = 0
            Case "prev"
                If intCurIndex <> 0 Then
                    GridView1.PageIndex = intCurIndex - 1
                End If
            Case "nex"
                If intCurIndex <> GridView1.PageCount Then
                    GridView1.PageIndex = intCurIndex + 1
                End If
            Case "last"
                GridView1.PageIndex = GridView1.PageCount
        End Select

        GridView1.DataBind()
    End Sub
編集 履歴 (0)
  • こんにちは。
    ご提示ありがとうございました。
    一部参考にさせていただきました。
    -

どうしても GridView ということでなければ、ListView + DataPager を使ってはいかがですか? 実装例は以下のページが参考になると思います。

ListView でページ指定
http://surferonwww.info/BlogEngine/post/2010/11/13/Show-specified-page-of-ListView-programmatically.aspx

GridView でも同様なことができたかどうかは、ちょっと記憶にありません。思い出したら連絡しますが、あまり期待しないでください。

編集 履歴 (0)
  • いつもありがとうございます。
    GridViewでなければいけないということはなく、あくまでも一覧を作成できて1列にリンクが設定出来てって言うレベルにはなります。
    ご紹介いただいたページを参考に確認させてもらいます。
    -
  • 「一覧を作成できて1列にリンクが設定」はもちろん ListView で可能です。分からないところがあったら質問してください。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。