It's been a while since I last wrote an article. I like coding, but I'm not a very good writer. However, sometimes, I do feel the need to share my work to others. Maybe, just maybe, there's someone out there scratching his/her head off trying to solve the same problem I already solved. And recently, I had a eureka moment. I was so excited I tried sharing it to my girlfriend, but I got a blank stare in return. So, I'm sharing it to you!
Most of us had to deal with pagination. I noticed I've tackled this issue so many times before, but I never had a real solution. I never had a solution that made myself go "wow!" I always used a quick and dirty implementation just so I can get past it. Last week, that changed and today, I'm giving it to you!
You see, pagination is not as simple as it looks. True, you can throw in a few lines of code and voila! You've got yourself a working application. I've seen a lot of implementation myself, but nothing really satisfied me. Here's one example:
public IEnumerable<ComplexType> GetComplexTypes(int pageSize, int pageNumber)
.Skip(pageSize * (pageNumber - 1))
Okay, that looks good, you might say. It does give you the basic functionality of pagination. However, suppose I have a Grid View on my web page that should display the maximum page number in the footer section. How would I know what number to display?
Using the code
Before we dive right in to the details, let me show you how easy it is to use the code:
public class Repository<T> : IRepository<T>
private readonly IContext someContext;
public Repository(IContext someContext)
this.someContext = someContext;
public IEnumerable<T> GetComplexTypes(Paging paging)
public class SomeService
private readonly IRepository<ComplexType> repository;
public SomeService(IRepository<ComplexType> repository)
this.repository = repository;
public List<ComplexType> GetComplexTypes(int pageSize, int pageNumber, out int pageCount)
var paging = new Paging(pageSize, pageNumber);
var complexTypes = this.repository
pageCount = paging.PageCount;
That's pretty much all you need to know in terms of using the code, but it's probably better to understand how it works.
There are only 3 things you need to keep in mind to understand how it all works:
Paging class - a placeholder for all paging-related parameters such as the page size, page number, and the page count (like an out parameter).
PagedEnumerable class - implementation of
System.Collections.Generic.IEnumerable<T>. The most important logic is in this class.
EnumerableExtension class - extends the
System.Collections.Generic.IEnumerable<T> interface with a
The Paging class
Apart from having paging-related properties mentioned above, this class also takes care of calculating the value of the
PageCount property when the
CalculateAndSetPageCount() method is executed. You don't need to call this method yourself. This is invoked automatically in the
PagedEnumerable.DoGetEnumerator() method when an
Enumerable extension method such as
ToArray() is called. All you have to do is to pass an instance of this class to the
NOTE: As you may have noticed by now, I prefer using page number instead of page index. If you're more comfortable working with page index, feel free to modify the code to satisfy your needs.
The PagedEnumerable class
PagedEnumerable class is an
internal class and it is the most important component of the code. The magic happens in the
DoGetEnumerator() method. This method keeps count of all the items in the collection. However, it returns only those items that satisfy the conditions set against the
private IEnumerator<T> DoGetEnumerator()
var count = 0;
var size = 0;
var skip = this.paging.GetSkip();
var enumerator = this.collection.GetEnumerator();
if (++count <= skip)
if (++size > this.paging.PageSize)
yield return enumerator.Current;
As you can see, the
Paging.CalculateAndSetPageCount() method is called right before the the end of the
DoGetEnumerator() method is reached.
The Paginate method
This is the glue that holds all the components together. This is what communicates to the outside world. This is where the magic begins. This method simply returns a
PagedEnumerable<T> object as an
IEnumerable<T>. It's that simple. It's clean and it's elegant!
Thank you for reading my article! I hope you liked it. The best way for you to understand how the code works is to get your hands dirty. So, feel free to download and use it.
A word of caution: I have never used or tested this code in scenarios which involve big data sets. I don't expect it to work efficiently in such cases. So, use it with caution.
That' all folks. Happy coding!
- 17 July 2014: Initial version
- 17 July 2014: Fixed image link