My musings about .NET and what not

Resetting the Page Index in a ListView

Resetting paging in a GridView is way easy. For a ListView, not so much. There's actually no such property as PageIndex with ListView, so we need to dig into the internals of the DataPager to perform this common task.

There are lots of situations in which you need to set a paged list of data back to the first page in code. For example, let's say you search your database by specifying some search criteria, and you get several pages of results. Using the supplied paging controls, you jump to different pages -- page 1... page 2... page 3... and then, you decide to alter the search criteria. You certainly don't want the new set of results to start on page 3! Of course, you'd want to see the new results starting again from the first page.

To provide a concrete example, let's use the Products table from the Northwind database. This sample database contains data about various food products, each of which belong to a certain category -- Beverages, Condiments, Confections, and so on. If we set up a simple page that lists product data by category, we might end up with something that looks like the following:

 

In the screenshot above, you can see we're filtering the products table by category. The category to search for is specified using a DropDownList. The results are displayed in a paged GridView below that. The PageSize property of the GridView is set to 5, meaning a maximum of 5 results will be displayed per page.

If we flip through the results to a page greater than 1, then set the categories dropdown to a new category, we'll get new results, but those results won't start on the first page as we might expect (unless there's only one page of data, of course). Whenever you cause the contents of the list to change, you have to reset the display back to the first page in code.

As you are no doubt aware, the PageIndex property of a GridView gets or sets the zero-based index of the currently displayed page. Resetting the GridView back to the first page of data is trivial -- you simply set PageIndex = 0. In this case, you'd do that whenever the SelectedIndex  changes on the Categories dropdown.

protected void ddlCategories_SelectedIndexChanged(object sender, EventArgs e)
{
   gvProducts.PageIndex = 0;
}

This is possible because the paging controls are integral to the GridView itself. But that isn't so with a ListView. The ListView control has no paging controls of its own, and thus no PageIndex property. The ListView actually requires support from a DataPager control to provide paging functionality. So, how do we create the same behavior using the ListView and DataPager?

Example 1: DataPager with NumericPagerField

Reproducing the results grid in a ListView is pretty standard stuff, so I won't show all of that here. Providing paging support through the DataPager is pretty easy as well. In our example above, the GridView provides paging functionality through the use of page number links. We can do the same with the DataPager by adding a NumericPagerField to the Fields collection of the DataPager. We'll set the PagedControlID to the ID of our ListView , and set its PageSize property to 5.

<asp:DataPager ID="dpgProducts" runat="server" PagedControlID="lvProducts"
   PageSize="5">
   <Fields>
      <asp:NumericPagerField />
   Fields>
asp:DataPager>

This results in the following page:

So far, we've recreated all the functionality of our original GridView -based page, except for resetting the paged results when the dropdown changes. Unfortunately, that's a bit more involved than just setting a property.

The key to pulling this off is to think about how we do it manually, and then recreate that functionality in code. In this case, to "manually" set the results of this ListView on the screen back to the first page, we would click the "1" LinkButton in the DataPager. So, we need to recreate that -- to somehow "click" the "1" LinkButton in the DataPager -- not manually of course, but with code.

The NumericPagerField class derives from the DataPagerField class and overrides its HandleEvent method. HandleEvent is a helper method that handles events that occur in a DataPagerField. In the case of the NumericPagerField, clicking a page number raises an event. This raised event has a CommandName value that is equal to one less than the number that was clicked (remember, the index is zero-based). For example, when you click on the number "1", a LinkButton OnClick event is raised with CommandName of 0. We can simulate this event in code by encapsulating the proper event data in a CommandEventArgs object, then passing it to the HandleEvent method. Once we do that, our application should behave exactly as though we clicked on the "1" button with the mouse.

We can do that as follows:

protected void ddlCategories_SelectedIndexChanged(object sender, EventArgs e)
{
   CommandEventArgs commandEventArgs = new CommandEventArgs("0", "");
   NumericPagerField numericPagerField = dpgProducts.Fields[0] as NumericPagerField;
   if (numericPagerField != null)
   {
      numericPagerField.HandleEvent(commandEventArgs);
   }
}

In the above code, we first create a CommandEventArgs object with a CommandName of 0. Then, we extract the NumericPagerField object from the DataPagerFieldCollection. Then assuming that worked, we pass the CommandEventArgs object we created to the HandleEvent method of the NumericPagerField. This sets the list of data back to the first page.

Example 2: DataPager with NextPreviousPagerField

Let's now assume you decide, instead of letting users click numbers to jump to any page, you only want to allow users to flip through one page at a time. You could do that with a NextPreviousPagerField:

<asp:DataPager ID="dpgProducts" runat="server" PagedControlID="lvProducts"
   PageSize="5">
   <Fields>
      <asp:NextPreviousPagerField />
   Fields>
asp:DataPager>

Resetting data paging here is almost the same as before. The only thing to remember is, with a NextPreviousPagerField, the CommandName value of the event that navigates to the first page is "First", not "0". (Technically, the CommandName value is actually DataControlCommands.FirstPageCommandArgument, which is merely a constant that represents the string "First"). Therefore, the logic is very similar:

protected void ddlCategories_SelectedIndexChanged(object sender, EventArgs e)
{
   CommandEventArgs commandEventArgs = new CommandEventArgs("First", "");
   NextPreviousPagerField nextPreviousPagerField = dpgProducts.Fields[0] as NextPreviousPagerField;
   if (nextPreviousPagerField != null)
   {
      nextPreviousPagerField.HandleEvent(commandEventArgs);
   }
}

The only difference here is the type of DataPagerField whose HandleEvent method we're invoking, and the CommandName value we're passing to it.

Example 3: DataPager with TemplateField

With the NumericPagerField and the NextPreviousPagerField, you can see that the actual work of paging itself is being handled automatically for us. We're not handling any button clicks, we're not examining any command event data, and we're not setting any start row indexes every time. We click, the list pages, and life is sweet.

However, the DataPager also lets us use a TemplateField to page data. The cool thing about the TemplateField is that you can really go wild with it, pretty much defining any kind of paging scheme you can imagine. The downside is that the TemplateField provides no automatic paging functionality at all. You've got to do it all on your own, including providing your own postback-enabled controls and CommandName values.

Take a look at the the following paging example:

Here we've set up custom LinkButtons that, instead of showing words like "First", "Previous", or "Next", show the record numbers. In the screenshot, we can see from the pager that records 6 through 10 of the results are bring displayed. There are buttons that let us go to records 1 - 5 or 11 - 12. There is also a "<<" button that lets us go back to the first page.

Below is the markup that renders the pager in shown above. Don't get bogged down in all the databinding going on here; all that's really important to note is the first LinkButton:

"dpgProducts" runat="server" PagedControlID="lvProducts"
   PageSize="5">
   
      "TemplatePagerField_OnPagerCommand">
         
            "lnkbFirst" runat="server" CommandName="FirstPage"
               Text="<<" Enabled='<%# Container.StartRowIndex > 0 %>' />
            "lnkbPrevious" runat="server" CommandName="PreviousPage"
               Text='<%# (Container.StartRowIndex - Container.PageSize + 1) + " - " + (Container.StartRowIndex) %>'
               Visible='<%# Container.StartRowIndex > 0 %>' />
            
            "lnkbNext" runat="server" CommandName="NextPage"
               Text='<%# (Container.StartRowIndex + Container.PageSize + 1) + " - " + (Container.StartRowIndex + Container.PageSize*2 > Container.TotalRowCount ? Container.TotalRowCount : Container.StartRowIndex + Container.PageSize*2) %>'
               Visible='<%# (Container.StartRowIndex + Container.PageSize) < Container.TotalRowCount %>' />
         
      
   

              

Note that the first LinkButton (with ID="lnkbFirst") has the CommandName = "FirstPage". That's the button we'll wire up to jump to the first page. Below is the code that does that, along with the code for the other buttons as well:

protected void TemplatePagerField_OnPagerCommand(object sender, DataPagerCommandEventArgs e)
{      
   int maximumRows = dpgProducts.MaximumRows;
   switch (e.CommandName)
   {
      case "FirstPage":
         e.NewStartRowIndex = 0;
         e.NewMaximumRows = maximumRows;
         break;
      case "NextPage":
         int newIndex = e.Item.Pager.StartRowIndex + maximumRows;
         if (newIndex <= e.TotalRowCount)
         {
            e.NewStartRowIndex = newIndex;
            e.NewMaximumRows = maximumRows;
         }
         break;
      case "PreviousPage":
         e.NewStartRowIndex = e.Item.Pager.StartRowIndex - maximumRows;
         e.NewMaximumRows = maximumRows;
         break;         
   }
}

In order to to accomplish template-driven paging on a ListView, you handle the OnPagerCommand event of the TemplateField. In this event handler, you have to determine which control was clicked (you do this via the CommandName) and then set the value of the NewStartRowIndex and NewMaximumRows properties of the DataPagerCommandEventArgs object accordingly.

We can now reset the paging as we did before, by passing the appropriate CommandName to the HandleEvent method.

protected void ddlCategories_SelectedIndexChanged(object sender, EventArgs e)
{
   CommandEventArgs commandEventArgs = new CommandEventArgs("FirstPage", "");
   TemplatePagerField templatePagerField = dpgProducts.Fields[0] as TemplatePagerField;
   if (templatePagerField != null)
   {
      templatePagerField.HandleEvent(commandEventArgs);
   }
}

Conclusion

To set a paged ListView back to the first page, just follow these basic steps:

  1. Create a handler for any event that causes the displayed data to change. This could be a search/filtering action as in our example, insertion/deletion of data, or whatever.
  2. Determine the CommandName value that brings you to the first page, based on the type of DataPagerField you're using.
  3. In the event handler (from step 1), create a CommandEventArgs object using the CommandName value (from step 2).
  4. From the Fields collection of the DataPager, get the field that fires the event that brings you to the first page.
  5. Pass the CommandEventArgs object (from step 3) to the HandleEvent method of the field (from step 4).

That's all folks. Happy paging!

Subscribe to this blog for more cool content like this!

kick it on DotNetKicks.com

shout it on DotNetShoutOut.com

vote it on WebDevVote.com

Bookmark / Share

    » Similar Posts

    1. Nested ListViews and More - Working with Databound Controls Inside the ListView
    2. Defensive Programming, or Why Exception Handling Is Like Car Insurance
    3. Building a TweetThis Extension with Automatic Bit.ly for Graffiti CMS

    » Trackbacks & Pingbacks

    1. You've been kicked (a good thing) - Trackback from DotNetKicks.com

      Resetting the Page Index in a ListView — March 2, 2009 1:55 PM
    2. Thank you for submitting this cool story - Trackback from DotNetShoutout

      Resetting the Page Index in a ListView — March 3, 2009 9:04 AM
    3. Pingback from Twitter Trackbacks for Resetting the Page Index in a ListView : LeeDumond.com [leedumond.com] on Topsy.com

      Twitter Trackbacks for Resetting the Page Index in a ListView : LeeDumond.com [leedumond.com] on Topsy.com — November 28, 2009 2:17 PM
    Trackback link for this post:
    http://leedumond.com/trackback.ashx?id=44

    » Comments

    1. Jeff Kingery avatar

      Thanks for posting this. There's a dearth of good information out there on the DataPager (perhaps because it sucks?) and this was just what I needed.

      Jeff Kingery — April 22, 2009 9:52 AM
    2. Tracy Howell avatar

      I have spent many many hours on this problem. Thank you for this solution. Now I can move on.

      Thanks, again

      Tracy Howell — May 13, 2009 9:34 PM
    3. Lee Dumond avatar

      Glad it helped you out!

      Lee Dumond — May 13, 2009 10:32 PM
    4. Steve M avatar

      You can simplify some of the above by using the SetPageProperties method of the DataPager.

      For the first example, just call it within ddlCategories_SelectedIndexChanged, with something like:

      myDataPager.SetPageProperties(0, myDataPager.PageSize, false);

      Steve M — June 10, 2009 9:50 AM
    5. ugur erdem avatar

      Thanks :)

      ugur erdem — September 28, 2009 3:16 AM
    6. murat turan avatar

      good work, thanks.

      murat turan — March 15, 2010 8:36 PM
    7. murat turan avatar

      good work, thanks..

      murat turan — March 15, 2010 8:37 PM
    8. Austin IT Support avatar

      I wanted to thank you for this great read!! I definitely enjoying every little bit of it I have you bookmarked to check out new stuff you post...

      Austin IT Support — April 16, 2010 1:38 AM
    9. Dallas IT Support avatar

      Hi vey nice interesting blog im from leeds i found this on msn I'm in the crane hire company business, i found this blog very interesting good luck with it i will return to this blog soon

      Dallas IT Support — April 16, 2010 1:38 AM
    10. Suraj avatar

      Good post saved my time . thanks

      Suraj — May 6, 2010 4:18 AM
    11. ipad chargers avatar

      My day is incomplete without having a nice tip from professionals like you.

      ipad chargers — June 5, 2010 7:26 AM
    12. Italian to English translation avatar

      That's great advice on paging and your examples are magnificent.

      Italian to English translation — June 6, 2010 5:17 PM
    13. dian avatar

      great post. . thank you.

      dian — July 5, 2010 11:00 PM
    14. Giovanni A. avatar

      Great! This helped me a lot!!!

      Tnx

      Giovanni A. — August 6, 2010 3:51 AM
    15. Sania avatar

      Nice work.

      Thanks.

      Sania — August 18, 2010 7:02 AM
    16. online bingo bonus avatar

      I rolled out McAfee agents to about ten servers yesterday and four of them wouldn’t show up properly

      online bingo bonus — September 7, 2010 10:47 AM
    17. Online Defensive Driving Texas avatar

      I have a list that I am a Paging display data. I want to first page of the game on the pager Page_Load. I tried the data page Pager.Set properties of the method, but it is not doing what I need. Thanks for your help here.

      Online Defensive Driving Texas — September 14, 2010 1:35 AM
    18. Guillem avatar

      You can locate a DataPager inside another control and set it's page index.

      // Set page to first

      DataPager pager = (DataPager)lvViewTexts.FindControl("DataPagerTexts");

      if (pager != null)

      {

      pager.SetPageProperties(1, pager.PageSize, true);

      }

      Guillem — September 15, 2010 7:21 AM
    19. Philipp avatar

      Thanks for that! Helped me alot

      Philipp — October 19, 2010 7:34 AM
    20. kompanzasyon avatar

      sdadaad

      kompanzasyon — November 8, 2010 4:37 PM
    21. kompanzasyon avatar

      There is no exact formula, or panel of experts that will be able to determine the exact dollar amount which should be spent in each area, nor is there a correct percentage by which the money should be divided between the two areas

      kompanzasyon — November 8, 2010 4:37 PM
    22. kalibrasyon avatar

      I have a list that I am a Paging display data. I want to first page of the game on the pager Page_Load. I tried the data page Pager.Set properties of the method, but it is not doing what I need.

      kalibrasyon — November 8, 2010 4:38 PM
    23. Rugby Jerseys avatar

      This is a big help indeed. At last I found what I was looking for. Keep up the good work and thanks a lot for sharing your technical knowledge here.

      Rugby Jerseys — November 16, 2010 1:44 AM
    24. jobs avatar

      it's worked on my project. thanks for sharing.

      jobs — December 7, 2010 3:42 AM
    25. San Diego Mortgage Guy avatar

      Wow! looks like I need to go back to 101 because this is all WAY over my head

      San Diego Mortgage Guy — December 16, 2010 12:43 PM
    26. stag party ideas avatar

      Great guide. I've been trying to find out how to do this for ages, thanks a lot.

      stag party ideas — December 30, 2010 2:53 AM
    27. herbalife avatar

      guide refreshing guide. my page display will work now. thanks problem solved.

      herbalife — January 18, 2011 12:04 PM
    28. herbalife avatar

      un guide tres bon. le data va rester sur et sain toujours. merci

      herbalife — January 18, 2011 12:06 PM
    29. ipad repair avatar

      I definitely enjoying every little bit of it I have you bookmarked to check out new stuff you post...

      ipad repair — January 19, 2011 6:41 AM
    30. sharepoint ad avatar

      Great guide. I've been trying to find out how to do this for ages, thanks a lot.

      sharepoint ad — January 20, 2011 5:29 AM
    31. herbalife avatar

      Thanks for the helpful hints, always appreciate articles like this

      herbalife — January 20, 2011 6:15 AM
    32. herbalife avatar

      Just what Ive been looking for great guide for someone like myself, will check back in the future

      herbalife — January 20, 2011 6:19 AM
    33. las vegas website design avatar

      After read this post i want to keep coming here again and again.Thanks a lot.

      las vegas website design — January 21, 2011 8:23 AM
    34. Baju Muslim avatar

      thats great. .

      thanks. . :)

      Baju Muslim — January 22, 2011 7:05 AM
    35. Tas Wanita avatar

      i found this article from google. .

      thanks for sharing my friend. . :D

      Tas Wanita — January 22, 2011 7:06 AM
    36. SEO Fighter avatar

      hello friend,link exchange with me please. .

      i waiting your response,thanks. .

      SEO Fighter — January 22, 2011 7:07 AM
    37. Personal Blog avatar

      thanks for information. .

      Personal Blog — January 22, 2011 7:09 AM
    38. Personal BlogDetik avatar

      really good,thanks. .

      Personal BlogDetik — January 22, 2011 7:11 AM
    39. News and Tech Update avatar

      link exchange with me please. . .

      News and Tech Update — January 22, 2011 7:11 AM
    40. Losing Weight avatar

      really helpful. .

      Losing Weight — January 22, 2011 7:12 AM
    41. All About Technology avatar

      great post. . !!!

      All About Technology — January 22, 2011 7:13 AM
    42. World of Computechno avatar

      really great post. .

      thank you. .

      World of Computechno — January 22, 2011 7:13 AM
    43. Baju Muslim Murah avatar

      thanks. . :)

      Baju Muslim Murah — January 22, 2011 7:15 AM
    44. Technology Newds Update avatar

      really support me. . :)

      Technology Newds Update — January 22, 2011 7:15 AM
    45. scott avatar

      Saved me hours - thanks!

      scott — January 25, 2011 11:47 PM
    46. utube avatar

      I'm using the ListView in multiple databases. This article helped me and saved many hours of work. Thank you.

      utube — January 27, 2011 2:00 AM
    47. Tom002 avatar

      This post hit the spot for my problems with listview! Thanks!

      Tom002 — March 30, 2011 8:09 AM
    48. Video Monitoring System avatar

      This is why I love .NET

      Video Monitoring System — April 18, 2011 7:07 AM
    49. auto body avatar

      Thanks for sharing.You wouldnt say how some websites are helpful source of informations like this one.Thanks

      auto body — June 22, 2011 8:21 AM

    » Leave a Comment