Home MVC Storefront

ASP.NET MVC: PagedList<T>

In some of his demos, ScottGu used a method that we didn't include in the MVCToolkit called "PagedList<T>", which basically pages a Linq query. I'm hoping to include this in the next drop of the Toolkit, but until then, I have the code for you :). Just drop this into a code file on your site, the Extension method will be picked up by any class "using" System.Web.Mvc:

using System;
using System.Collections.Generic;
using System.Linq;

namespace System.Web.Mvc
{
    public interface IPagedList
    {
        int TotalCount
        {
            get;
            set;
        }

        int PageIndex
        {
            get;
            set;
        }

        int PageSize
        {
            get;
            set;
        }

        bool IsPreviousPage
        {
            get;
        }

        bool IsNextPage
        {
            get;
        }     
    }

    public class PagedList<T> : List<T>, IPagedList
    {
        public PagedList(IQueryable<T> source, int index, int pageSize)
        {
            this.TotalCount = source.Count();
            this.PageSize = pageSize;
            this.PageIndex = index;
            this.AddRange(source.Skip(index * pageSize).Take(pageSize).ToList());
        }    
        
        public PagedList(List<T> source, int index, int pageSize)
        {
            this.TotalCount = source.Count();
            this.PageSize = pageSize;
            this.PageIndex = index;
            this.AddRange(source.Skip(index * pageSize).Take(pageSize).ToList());
        }
    
        public int TotalCount      
        { 
            get; set; 
        }
        
        public int PageIndex       
        { 
            get; set; 
        }
        
        public int PageSize 
        { 
            get; set; 
        }

        public bool IsPreviousPage 
        { 
            get 
            {
                return (PageIndex > 0);
            }
        }
        
        public bool IsNextPage 
        { 
            get
            {
                return (PageIndex * PageSize) <=TotalCount;
            } 
        }        
    }

    public static class Pagination
    {
        public static PagedList<T> ToPagedList<T>(this IQueryable<T> source, int index, int pageSize) 
        {
            return new PagedList<T>(source, index, pageSize);
        }

        public static PagedList<T> ToPagedList<T>(this IQueryable<T> source, int index)
        {
            return new PagedList<T>(source, index, 10);
        }        
    }
}
Troy DeMonbreun avatar
Troy DeMonbreun says:
Monday, December 10, 2007
Thanks!

Vijay S. avatar
Vijay S. says:
Monday, December 10, 2007
I added a TotalPageCount property to my copy, do u think this is a good idea?

Vijay S. avatar
Vijay S. says:
Monday, December 10, 2007
public int TotalPageCount { get { return (TotalCount / PageSize) 1; } } Also, when there's only one page of data, isNextPage has a bug it should be public bool IsNextPage { get { return ((PageIndex * PageSize)

Vijay S. avatar
Vijay S. says:
Monday, December 10, 2007
Actually, this works better return ((PageIndex 1) * PageSize)

Vijay S. avatar
Vijay S. says:
Monday, December 10, 2007
Sorry, copy n paste didn't work. TotalPageCount should be return (TotalCount / PageSize) 1;

Anastasiosyal avatar
Anastasiosyal says:
Monday, December 10, 2007
Cool stuff :) Minest of details but wouldnt you agree that it should be HasPreviousPage and HasNextPage rather than IsPreviousPage and IsNextPage?

mike avatar
mike says:
Tuesday, December 11, 2007
Sooo, under what licence is this code released, GPL v3? ;-)

mike avatar
mike says:
Tuesday, December 11, 2007
IsNextPage doesn't sound right imho. I would prefer IsFirstPage and IsLastPage.

Jim Zimmerman avatar
Jim Zimmerman says:
Wednesday, December 12, 2007
Cool stuff! I love these extension methods. One very cool thing about them is if someone really wants HasPreviousPage instead of IsPreviousPage or wants it be IsPP or DoesThisHaveAPreviousPage they can. Some conventions will really help, but for those who want their own, they can call it whatever they want.

Vijay Santhanam avatar
Vijay Santhanam says:
Wednesday, December 12, 2007
So true Jim, but if this is going to in a framework it definitely needs some descriptive naming. I found this class so useful on my first MVC app. I'm so glad to be done with Web.UI.Controls

Francois Tanguay avatar
Francois Tanguay says:
Monday, December 17, 2007
Just my 2 cents: IPagedList : IList ? PagedList Ctor should accept IEnumerable, hence having only 1 ctor. So should extension methods. AddRange(.... .ToList()); => ToList() isn't required. AddRange accepts any IEnumerable

jon paul davies avatar
jon paul davies says:
Wednesday, March 05, 2008
thanks for this. just what I need.

SubsoniC avatar
SubsoniC says:
Saturday, March 08, 2008
Why do this with LINQ when SubSonic already delivers? I'm not sure why there are two overlapping DALs at Microsoft, come to think of it...

Turhal Temizer avatar
Turhal Temizer says:
Monday, March 24, 2008
Thanks...


Search Me
Subscribe

Popular Posts
 
My Tweets
  • @codinghorror: I may be weird but I don't ask my cats to write my blog entries :p.
  • @blowdart sure! Wanna come on and do a webcast with me - plugging CardSpace in?
  • People are very, very weird. Skypecasts are creepy.
  • Is Rob Howard trying to tell us something? http://www.rob-howard.net/
  • New storefront posted- all about OpenID :) http://tinyurl.com/5rkgux
  About Me



Hi! My name is Rob Conery and I work at Microsoft on the ASP.NET team. I am the Creator of SubSonic and was the Chief Architect of the Commerce Starter Kit (a free, Open Source eCommerce platform for .NET)

I live in Kauai, HI with my family, and when my clients aren't looking, I sometimes write things on my blog (giving away secrets of incalculable value).