Data Navigation with the ListView, DataPager and SliderExtender Controls
As I mentioned in a previous post, I am currently researching what advantages ASP.NET 3.5's new ListView control would have over the GridView. To continue down this path, I thought it would be a good idea to look into how paging work with the ListView. To direct my research, I created a sample data table that supports paging via the standard paging buttons as well as with a slider bar. Below is a screenshot of the table. As usual you can follow the links below to view the live demo as well as download the code.
Download (.Net 3.5 and AjaxControlToolkit 3.5.11119.0) | Live Demo (IE6, IE7 and FF)
If you are interested in the implementation details, they are outlined below.
Overview of the DataPager Control
Before today, I had not yet worked with the DataPager. So to start off, I went out to MSDN's documentation and read through it. To summarize MSDN, the DataPager can be used to display paging navigation controls for other data-bound controls that implement the IPageableItemContainer interface (like the ListView). Additionally,
- The DataPager is associated with its data-bound control by using the PagedControlID, or if you are using a ListView, you just have to place the DataPager inside the ListView's LayoutTemplate (this is the approach I have taken)
- The DataPager contains a Fields collection, that can contain one of 3 different types of DataPagerFields: NextPreviousPagerField, NumericPagerField, and TemplatePagerField. Here is the rundown on these different field types (for this example, I used the TemplatePagerField).
- The DataPager also contains a few properties that can be used in databinding expressions when used in conjunction with the TemplatePagerField. For this sample, I used these properties to bind to the Slider controls value, tooltip as well as to generate the Paging status message (i.e. Page X of Y (Z items)).
Paging Math
One thing that bothers me about my previous paging implementations is how unless the last page of data is exactly the same as the page size, the data table will only be partially filled. The customers dataset taken from the Northwind database is a good example for this. There are 91 rows in the customers table. If you set your pagesize to 10 and navigate to the 9th row, you will only see 1 record (records 91 through 91). I would rather display 10 records (records 82-91).
So for this sample, I used the rules specified below to implement my custom paging behavior. The actual implementation is c# via a server side event handler, but I have got into the habit of pseudocding in JavaScript so ...
The DataPager provides a nice way to implement custom paging routines like the one described above. The TemplatePagerField defines a PagerCommand event that occurs when ever a button that is contained with the TemplatePagerField is clicked. So for this sample, I defined First, Previous, Next and Last buttons within the TemplatePagerField and assigned a CommandName to each of them. I then wired the PagerCommand event so that when my buttons are clicked I can calculate the parameters that define which rows are to be included in the next page of data. Here is the sample markup and PageCommand handler that I am using for this sample. If you download the code, you will see I have implemented the behavior outlined above in the PageCommand event handler.
Adding the SliderExtender Control
Besides providing paging buttons, I also wanted to give the user a nice slider bar that they can use to navigate through the data. If you haven't used the AjaxControlToolkit's Slider control before, here is a quick explanation of what it is ...
So I added the Slider control within the TemplatePagerField. By default, the slider allows the user to select values in a range from 0 to 100. I want to ensure that the user could only select a page that was in the valid range of available pages. For the scenario of 91 rows of customer data with a page size of 10, I didn't want the user to be able to select page 11. So I used the following markup to configure the control such that it would place the correct upperbound on the range of valid values:
Secondly, when the moves the Slider to change the selected page I want to post the form back to fetch the next page of data. Because the Slider extends a regular asp:TextBox, you can achieve this by setting the TextBox's AutoPostback attribute to True causing the form to submit when the user changes the Slider's value.
Below is the markup for the Textbox the Slider extends. There are a few important items:
- The Text property uses a databinding expression to determine what the current value should be. This way when the Pager buttons are used for navigation, the Slider's value stays in sync.
- AutoPostBack is set to true do the OnTextChange server event fires when the user changes the selected page
- I added an inline style of "display:none" so the TextBox doesn't flicker when the page is loaded
Conclusion
Well thats the rundown of how I used the ListView, DataPager and Slider controls to build a pretty sweet looking data table. I still have a few items that I would like to add to this example, including:
- Deciding what to do with the pager controls when the number of rows returned is less than the page size
- Add a progress indicator to the pager row that displays during partial postbacks
- Add mouseover images for the pager buttons
Hopefully I can get to these items later.
That's it. Enjoy!
Comments
Hi Matt,
Thanks once more for such an article.
And for your problem
"Deciding what to do with the pager controls when the number of rows returned is less than the page size"
If you like you can use this methodhttp://tech-review.org/blogs/.net_2.0/archive/2007/02/04/gridviews-and-adding-empty-rows-for-display-purposes-only.aspx
Hi Matt,
Nice job. i am not sure if that was by design, but I think there is a small bug.
Try going to the last page which will show you 82 to 91 and then start navigating back... now the pages show 72 to 81, 62 to 71, etc...
I would personally prefer it if the last page will show the second last page + the last page if the last page is less than the page size, so in this example your last page would show 81 to 91. if the last page size was 5 then the last page would be 81 to 95... but thats me...
Nice,
as always.
Quality article dude - Id add some feedback to show that dragging the slider is busy doing something - first time I looked at it I didnt think it was updating, after that I realised it was - doh!
Gregor
@emad -
Thanks for the feedback. I dont think I quite understand your technique. I am interested though, would you mind providing some code?
Matt.
@Gregor -
Good suggestion. You are right, its not exaclty obvious dragging the slider is doing anything.
Matt.
Useless...does not work in Opera. Will not use/recommend it for our work.
Hi. Nice article. Especially, paging thro slider..Something I never imagined. I tried to use DataPager with AJAX ReorderList by implementing IPageableItemContainer Interface. But it dosent seem to work. Can you tell me whats the difference between these two scenarios.
Matt
Nice articles as always, so with this demo, have you had a chance to be able to fetch only those rows that are displayed in the grid from the database? I like the slider, but watching sql profiler, it calls the same stored procedure everytime with all of the data? Just curious if you have ran into this using the objectdatasource? Thanks much!
Antonio
Matt
Great example, but how do I use it with custom sqp 2005 paging where I pull only a page of data from database and a total number of rows ?
Hi Matt,
i used the same technique in my project. When i navigating through datapager, i got an error. My application is in VB.net. Please help me on this.
error :
Invalid postback or callback argument. Event validation is enabled using in configuration or in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation
I get the same error as Sumith. It only happens when I use a drop down list to postback and update the table with new criteria, it seems like a viewstate issue, but it goes away when I use the standard pager control... :(
I resolved that error. I was building dynamic controls on the page and I just had to tweak the order things were occuring.
On another note, I am noticing that the slider in the tfoot of the table is causing some column sizing issues. For instance, I will set the first columns width to 60px and when i add the slider, it resizes it to the slider width... ??? weird.