views:

2665

answers:

3

Take the following example...a page with a ListView and a DataPager used for paging the data of the ListView:

Code Behind:

protected void Page_Load(object sender, EventArgs e)
{
    MyList.DataSource = GetSomeList();
    MyList.DataBind();
}

Source:

<asp:ListView ID="MyList" runat="server">
    <% //LayoutTemplate and ItemTemplate removed for the example %>
</asp:ListView>

<asp:DataPager ID="ListPager" PagedControlID="MyList" runat="server" PageSize="10">
    <Fields>
     <asp:NumericPagerField  />
    </Fields>
</asp:DataPager>

The problem with the DataPager is that it is always a step-behind with the binding.

For example, when the page loads it's on page number 1. Then when you click on page 3, it stays on page 1 after the postback. Then you click on page 5, and after the postback it finds itself on page 3...and after that you click on page 6, and it finds itself on page 5...and so on and so forth.

Why isn't the paging working as expected?

+6  A: 

Solution

The problem is due to the binding occuring on the Page_Load event.

For this to work as expected, the binding needs to happen in the DataPager's OnPreRender event, not in the Page_Load.

Source:

<asp:DataPager ID="ListPager" PagedControlID="MyList" runat="server" PageSize="10"
    OnPreRender="ListPager_PreRender">

<Fields>
     <asp:NumericPagerField  />
    </Fields>
</asp:DataPager>

Code Behind:

protected void Page_Load(object sender, EventArgs e)
{
    //Binding code moved from Page_Load
    //to the ListView's PreRender event
}

protected void ListPager_PreRender(object sender, EventArgs e)
{
    MyList.DataSource = GetSomeList();
    MyList.DataBind();    
}
Andreas Grech
A: 

I ran into this same problem, but binding everytime on datapager prerender was not an option for me. Instead, I was able to accomplish much the same thing by binding only when the paging occurred. This solution can be used as an alternative to the prerender solution by Andreas. The following worked for me:

By attaching to the ListView's PagePropertiesChanged event, I was able to correct the paging issue without having to bind on every prerender of the data pager.

NOTE: Most of the data pager properties are setup in a skin file, which is why they are not in the markup.

Markup:

<asp:DataPager ID="ListPager" runat="server" PagedControlID="MyList" />
<asp:ListView ID="MyList" runat="server">
    <% //LayoutTemplate and ItemTemplate removed for the example %>
</asp:ListView>

Code Behind:

protected void Page_Load(object sender, EventArgs e) {
   MyList.PagePropertiesChanged += new EventHandler(MyList_PagePropertiesChanged);
}

/// <summary>
/// Handles the situation where the page properties have changed.  Rebind the data
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MyList_PagePropertiesChanged(object sender, EventArgs e) {
   MyList.DataSource = GetSomeList();
   MyList.DataBind();
}
Jay S
Is your method also work for another control's postback event which causes listview to render itself to a default binding (null) ??If so I'm going to use your method in my project ..
Myra
I haven't tested that myself. From what I understand, the PagePropertiesChanged event only fires when the paging changes, not necessarilyy on every postback. If another control posts back, you would probably have to do the rebinding in the event handler for that other control. You'll have to try it and see.
Jay S