Tuesday, April 12, 2011

Using DataPager in ListView

If the DataSource is not known statically at design time, the DataPager may not work correctly. The following error could be expected to happen when you click on the link provided by DataPager at the second time:

Failed to load viewstate. The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request. For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request.

This problem occurs because the DataPager has no idea how to perform or calculate paging for you without knowing what page is supposed to display (i.e., StartIndex, and MaximuumRows in the page) when the DataSource is only known at runtime. Thus, you need to provide this missing piece of information to the DataPager before databinding.

Under Google search, you may find that quite a few people implemented the PreRender event of DataPager to perform databinding. Unfortunately, it doesn't work for this scenario. You can bind the data at DataPager's PreRender event but you are unable to supply paging properties to DataPager as mentioned above. Both StartRowIndex and MaximumRows properties are needed to set for paging before databinding. This problem took me a few hours to resolve. It turns out that the solution is very simple.

The Solution: You should add and implement the PagePropertiesChanging event of ListView. The PagePropertiesChangingEventArgs from the event argument will provide all your needy paging properties (StartRowIndex and MaximumRows) so that you can supply them to the DataPager.

    protected void ListView1_PagePropertiesChanging(object sender, PagePropertiesChangingEventArgs e) {     
      this.DataPage1.SetPageProperties(e.StartRowIndex, e.MaximumRows, false);
      BindData();  // set DataSource to ListView and call DataBind() of ListView
    }

If the DataPager is placed inside the ListView, do this:

    protected void ListView1_PagePropertiesChanging(object sender, PagePropertiesChangingEventArgs e) {
      ListView lv = sender as ListView;
      DataPager pager = lv.FindControl("DataPage1") as DataPager;
      pager.SetPageProperties(e.StartRowIndex, e.MaximumRows, false);
      BindData();  // set DataSource to ListView and call DataBind() of ListView
    }

11 comments:

  1. Thanks, you saved some head banging for me!

    ReplyDelete
  2. Good stuff there. I'm pretty familiar with the gridview but am trying to migrate to the listview and this was a definite help!

    ReplyDelete
  3. hey! I'm using a listview with datapager, however, when I click go to the second page,I'm able to see the data but the first page link remains inactive. How to over come this issue.

    Thanks in advance.

    ReplyDelete
  4. Thank's a lot :) Saved my day.

    ReplyDelete
  5. Perfect!!! :)

    This is the kind of blog post one wants to find.

    It is like finding the grains of gold after just finding sand for a long time. Thank you!

    ReplyDelete
  6. thnks man...u save my day..........:)

    ReplyDelete
  7. I know this was posted froma while back but I'm having this problem and your solution did not work for me, and shouldn't it be DataBind() not BindData()?

    ReplyDelete
    Replies
    1. Katherine, BindData() is my function which will set DataSource to ListView and call DataBind(). It is addressed at my code comment. You must have missed it.

      Delete