Search code examples
c#asp.netlistviewdatapager

ASP DataPager returning incorrect StartRowIndex


I have a ListView with a DataPager. The ListView is bound to a DataTable in the code-behind.

So, say I set the Pager to show 10 page links and I have more than 10 pages worth of data. Those 11 buttons (the 10 pages plus the overflow ellipses that points to page 11) work just fine. The Next and Previous links work fine, as well.

First page of pages

However, once I click on the ellipses and go to page 11, the links still point to offsets from the first page of pages. That is, clicking on page 12 will dump me at page 3 (page 1 being the new page 10 ellipses, page 2 being page 11). The same with the Next and Previous links and all the other numeric links.

Second page of pages

Looking at the code in the browser console, it looks like even (other people's) Pagers that are working print the same arguments in the links' __doPostBack call for each page of pages. So, I'm not sure how the Pager is retaining its overall offset, since each page of pages just gives offsets relative to themselves.

I'm really at a loss for what I'm doing differently from other people, aside from binding my ListView to a DataTable in the code-behind rather than a data source in the DataSourceID attribute. But, the Pager does paginate properly for the first page of pages so I don't think it's just my binding that's throwing it off.

<asp:ListView ID="lvProjects" runat="server" GroupPlaceholderID="groupPlaceHolder"
    ItemPlaceholderID="itemPlaceHolder" OnPagePropertiesChanging="OnPagePropertiesChanging"
    DataKeyNames="ProjectID" OnPreRender="lvProjects_PreRender">
    <LayoutTemplate>
            <asp:DataPager ID="DataPager" runat="server" PagedControlID="lvProjects" PageSize="10">
                <Fields>
                    <asp:NextPreviousPagerField ButtonType="Link" ShowFirstPageButton="true" ShowPreviousPageButton="true" ShowNextPageButton="false"
                        FirstPageText="|&lt;&lt;" PreviousPageText="&lt;" RenderNonBreakingSpacesBetweenControls="true" />
                    <asp:NumericPagerField ButtonType="Link" ButtonCount="10" RenderNonBreakingSpacesBetweenControls="true" />
                    <asp:NextPreviousPagerField ButtonType="Link" ShowNextPageButton="true" ShowLastPageButton="true" ShowPreviousPageButton="false"
                        NextPageText="&gt;" LastPageText="&gt;&gt;|" RenderNonBreakingSpacesBetweenControls="true" />
                </Fields>
            </asp:DataPager>
        <br />
        <br />
        <table class="myGrid projects-table">
            <tbody>
                <asp:PlaceHolder ID="itemPlaceHolder" runat="server" />
            </tbody>
        </table>
    </LayoutTemplate>
    <ItemTemplate>
       ...
    </ItemTemplate>
</asp:ListView>

.

protected void OnPagePropertiesChanging(object sender, PagePropertiesChangingEventArgs e)
{
        var pager = (DataPager)lvProjects.FindControl("DataPager");

        pager.SetPageProperties(e.StartRowIndex, e.MaximumRows, false);

        lvProjects.DataSource = Projects;
        lvProjects.DataBind();
}

Looking at e.StartRowIndex will also show the first page of page's offsets for higher pages (ie. page 12 will return "20", @10 items/page).


Solution

  • This was apparently due to overriding the PageStatePersister with a SessionPageStatePersister as so:

    protected override PageStatePersister PageStatePersister
    {
        get
        {
            return new SessionPageStatePersister(this);
        }
    }
    

    I'm guessing the DataPager stores its overall offset in the page state and that was somehow getting lost when I changed the page state's behavior.

    Removing the override allowed it work as intended.