Since ASP.NET does not provide paging for repeaters, and I could not find any material out there that would work in a user control, I decided to create my own custom paging. Most examples I saw used dynamically created controls for paging. As dynamically created controls go, they tend to cause more problems than the problem they solve, especially when you're planning to modify them. Don't blame the coders, wiring up dynamically created controls correctly requires an intricate knowledge of the ASP.NET page life cycle. I however felt that in most cases a simpler version would do, so I opted for statically created paging controls.
Let's say that I have a simple repeater in my user control:
I'm going to add a placeholder for my paging controls.
Notice how i'm using only 4 link buttons, which might not be adequate for most situations. So the idea is to dynamically change the properties of these link buttons depending on the current page.
Once we have a way to keep track of the current page we are on as well as the total number of data items(or pages), we are well on our way to finishing our control.
To deal with keeping track of the current page and total number of data items, i'm going to use control state here. I could have used Viewstate instead for simplicity but there's a possibility of viewstates being turned off by another developer using my control, and in a critical feature such as paging, it's better to store state in a control state.
Here's the code to make that work:
I'm using a structure to store my state specific properties here. The SaveControlState and LoadControlState methods are used by ASP.NET to serialize and deserialize my structure into control state.
The things remaining to do are to load data and also to format our control dynamically based on the page we are at. Let's look at loading data first:
I initialize page load to fire our data loading method the first time the page is called.
The actual loading is done like this:
The important thing to note here is that we use a PagedDataSource as our datasource for the repeater, not the data items directly. This is because the repeater control does not support paging out of the box. To enable paging, we need to use the PagedDataSource as an adapter, whose properties such as the size of the page can now be set.
For formatting the output of the page links, I use the following method:
Here n has been set to 4, since we are using 4 linkbuttons in our ascx file. If we wish to add more buttons and spacers (which are to add seperation between the buttons), it would be as simple as adding those controls following the same naming convention as the other buttons, and changing the value of n.
For eg. let's say that we have 7 pages, and are currently in the second page.
The paging would look like " Prev 2 3 4 5 Next"
2 would be disabled. If you look at the ascx file again, you'll notice that the linkbuttons were hardcoded with values 1 to 4. The values have now been dynamically changed.
The following code performs event handling for the page buttons. If you look at the LoadItemsBasedOnCurrentPage() method, you will find that the method the call to LoadData fetches only items we will require on the current page. This results in a smaller payload of information being sent at each access to a page.
That's about it. All you need to do is to add you own method to get all the data items, change items per page (which i have deliberately set to the ridiculous value of 2) and bind them however you see fit.
This example, can with a bit of care, be easily extended to support "jump to first, last" or having .. paging feature, where you can jump to the middle of the page list. However, I have not included that for the sake of simplicity.
Happy plagiarizing. Just kidding, you have my blessings.