8

ASP.NET 4.5 および 4.5.1 バージョンで GridView ページャーの問題を発見しました。.NET 2 - 4 以降、このような問題は経験したことがありません。

要するに、次のようなコードビハインドでデータを入力しているグリッドビューがあります。

protected int CurrentPage { get { return SearchResults.PageIndex + 1; } }

protected void Page_Load(object sender, EventArgs e)
{
    if(!IsPostBack)
         BindGrid();
}

private void BindGrid()
{
    int totalRowCount = 0;
    SearchResults.DataSource = GetPageData(SearchResults.PageIndex, SearchResults.PageSize, out totalRowCount);
    SearchResults.VirtualItemCount = totalRowCount;                   
    SearchResults.DataBind();
}

private IEnumerable GetPageData(int start, int count, out int totalRowCount)
{
    return Membership.GetAllUsers(start, count, out totalRowCount);
}

protected void SearchResults_PageIndexChanging(object sender, GridViewPageEventArgs e)
{            
    SearchResults.PageIndex = e.NewPageIndex;            
    BindGrid();
}

問題は、GridView の最後のページにヒットして他のページに戻ろうとすると、PageIndexChanging が起動しないことです。この問題は、最後のページのレコード数が PageSize と同じでない場合にのみ発生します。動作は、ページがリロードされ、グリッドビューのページが PageSize までの空のデータ行で満たされることです。VirtualItemCount は、ItemCount の合計を正しく表します。

マークアップ、そこに何かが見つかった場合:

<asp:GridView runat="server" CellPadding="0" CellSpacing="0" GridLines="None" CssClass="table table-condensed table-striped table-footer"
        ID="SearchResults" AllowCustomPaging="true" AllowPaging="true" PageSize="6" OnPageIndexChanging="SearchResults_PageIndexChanging" AutoGenerateColumns="false" UseAccessibleHeader="true">
...
<PagerTemplate>
            <span class="pull-left">
                <strong><%= SearchResults.PageIndex * SearchResults.PageSize + 1 %></strong> - <strong><%= CurrentPage * SearchResults.PageSize %></strong>
            </span>
            <span class="pull-left">
                Total records: <strong><%= SearchResults.VirtualItemCount %></strong>
            </span>
            <ul class="pagination pull-right">
                <li><asp:LinkButton runat="server" CommandName="Page" CommandArgument="First"><span class="glyphicon glyphicon-backward"></span></asp:LinkButton></li>

                <li><asp:LinkButton runat="server" CommandName="Page" CommandArgument="<%# CurrentPage - 2 %>" Visible="<%# CurrentPage > 2 %>"><%= CurrentPage - 2 %> </asp:LinkButton></li>
                <li><asp:LinkButton runat="server" CommandName="Page" CommandArgument="<%# CurrentPage - 1 %>" Visible="<%# CurrentPage > 1 %>"><%= CurrentPage - 1 %> </asp:LinkButton></li>
                <li class="active"><a href="#"><%= CurrentPage %></a></li>
                <li><asp:LinkButton runat="server" CommandName="Page" CommandArgument="<%# CurrentPage + 1 %>" Visible="<%# CurrentPage < SearchResults.PageCount %>"><%= CurrentPage + 1 %></asp:LinkButton></li>
                <li><asp:LinkButton runat="server" CommandName="Page" CommandArgument="<%# CurrentPage + 2 %>" Visible="<%# CurrentPage < SearchResults.PageCount - 1 %>"><%= CurrentPage + 2 %></asp:LinkButton></li>

                <li><asp:LinkButton runat="server" CommandName="Page" CommandArgument="Last"><span class="glyphicon glyphicon-forward"></span></asp:LinkButton></li>
            </ul>
        </PagerTemplate>
</asp:GridView>

どうもありがとう、私は何日もこれに対処してきました。もちろん、QueryString アプローチを使用することもできますが、多くのテーブルを使用するため、可能であればポストバック アプローチを使用したいと考えています...


編集:

私が見つけた最も簡単な回避策は、すべての Page_Load で BindGrid を実行することでした。何らかの理由で、LastPageSize == PageSize でない限り、PageIndexChanging は最後のページで発生しません。次に、CommandArguments をバインドするために DataBind が呼び出されないため、正しくポストバックできません。

一方、それはあまり明確ではなく、問題を引き起こす可能性があります...少なくとも二重バインディング=ページ変更時のデータに対するSQLへの二重呼び出し...そうでなければ、ここでPageIndexChangingを強制する方法がわかりません。私への.NETの問題。

4

2 に答える 2

0

これは私にも起こることがわかりました。ポストバックでは、データの後の最初の行を除いて、最後のページが最初のページの行で最後のページに「入力」されます。例: ページ サイズが 10 で、25 行あるとします。最後のページには、最初は行 21 ~ 25 が表示され、ポストバックで行 7 ~ 10 が追加されます。

これらのファントム行の描画を防ぐために、次の「ハック」をグリッドビューの RowCreated に追加しました。GV はグリッドビューです。DataRowCount は、データソースから行数を返す関数です。PageIndex は、セッションを使用して現在のページ インデックスを保持するプロパティです。

        If e.Row.RowType = DataControlRowType.DataRow Then
        Dim RowsLeft As Integer = DataRowCount() - (GV.PageSize * PageIndex)
        Dim RowsExpected As Integer

        If RowsLeft > GV.PageSize Then
            RowsExpected = GV.PageSize
        Else
            RowsExpected = RowsLeft
        End If

        If e.Row.RowIndex >= RowsExpected Then
            'Last page isn't full, need to force writing nothing out for extra rows
            e.Row.SetRenderMethodDelegate(New RenderMethod(AddressOf RenderNothing))
        End If
    End If

そして、次の機能を追加しました。

Public Sub RenderNothing(writer As HtmlTextWriter, container As Control)
End Sub

RowCreated は ViewState が読み込まれる前に発生するため、GV の PageIndex は利用できませんでした。そこで、PageIndex を保持するプロパティを作成しました。したがって、私のコードは新しいプロパティを更新し、プロパティはそれをセッションに保存して GV のプロパティを更新します。そして、これは私が追加したプロパティです

Private Const SS_PagerControl_PageIndex As String = "SSPagerControl_PageIndex"
<Bindable(True), CategoryAttribute("Paging"), DefaultValue("0")>
Public Property PageIndex As Integer
    Get
        If Session(SS_PagerControl_PageIndex) Is Nothing Then
            Return 0
        End If

        Return CInt(Session(SS_PagerControl_PageIndex))
    End Get
    Set(ByVal value As Integer)
        Session(SS_PagerControl_PageIndex) = value
        GV.PageIndex = value
        RebindGrid()
    End Set
End Property
于 2015-06-23T21:55:10.027 に答える