ASP.NET MVC – Pagination View User Control
Each website, content management system, blog and so on need "pagination". A never ending site with "foo-entries" is not very professional. Thats why i created for my ASP.NET MVC sample (a kigg / dotnetnuke similar page) a specific"Pagination View User Control"
In almost every "List" View I implemented my control:
The advantages of such an control:
- look and feel is on each page the same
- changes are very easy to implement
In my sampel I use this CSS design.
Structure
A typical MVC View User Control
Code
Pagination.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Pagination.ascx.cs" Inherits="Mvc2.Views.Shared.Pagination" %>
<ul class="pagination-clean">
<% if (ViewData.HasPreviousPage)
{ %>
<li class="previous"><a href="<%=ViewData.PageActionLink.Replace("%7Bpage%7D", (ViewData.PageIndex - 1).ToString())%>">« Previous</a></li>
<% }
else
{ %>
<li class="previous-off">« Previous</li>
<% } %>
<%for (int page = 1; page <= ViewData.TotalPages; page++)
{
if (page == ViewData.PageIndex)
{ %>
<li class="active"><%=page.ToString()%></li>
<% }
else
{ %>
<li><a href="<%=ViewData.PageActionLink.Replace("%7Bpage%7D", page.ToString())%>"><%=page.ToString()%></a></li>
<% }
}
if (ViewData.HasNextPage)
{ %>
<li class="next"><a href="<%=ViewData.PageActionLink.Replace("%7Bpage%7D", (ViewData.PageIndex + 1).ToString())%>">Next »</a></li>
<% }
else
{ %>
<li class="next-off">Next »</li>
<% } %>
</ul>
Pagination.ascx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Mvc2.Views.Shared
{
public class PaginationViewData
{
public int PageIndex { get; set; }
public int TotalPages { get; set; }
public int PageSize { get; set; }
public int TotalCount { get; set; }
public string PageActionLink { get; set; }
public bool HasPreviousPage
{
get
{
return (PageIndex > 1);
}
}
public bool HasNextPage
{
get
{
return (PageIndex * PageSize) <= TotalCount;
}
}
}
public partial class Pagination : System.Web.Mvc.ViewUserControl<PaginationViewData>
{
public Pagination()
{
}
}
}
The ViewData is strongly typed by the PaginationViewData class.
How to use – Helper "PagedList"
It is very easy to use, if you are already use the PageList class:
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
namespace Mvc2.Helpers
{
public class PagedList<T> : List<T>
{
public PagedList(IQueryable<T> source, int index, int pageSize)
{
this.TotalCount = source.Count();
this.PageSize = pageSize;
this.PageIndex = index;
this.AddRange(source.Skip((index - 1) * pageSize).Take(pageSize).ToList());
int pageResult = 0;
for (int counter = 1; pageResult < this.TotalCount; counter++)
{
pageResult = counter * this.PageSize;
this.TotalPages = counter;
}
}
public int TotalPages
{
get;
set;
}
public int TotalCount
{
get;
set;
}
public int PageIndex
{
get;
set;
}
public int PageSize
{
get;
set;
}
public bool HasPreviousPage
{
get
{
return (PageIndex > 1);
}
}
public bool HasNextPage
{
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);
}
}
}
The original code wrote Rob Conery – in my version is the first page the number 1, not 0 – a user could confused by the link to page number 0
How to use- in the view page
I render the control by using the in-build "Html.RenderUserControl" helper:
<%=Html.RenderUserControl("~/Views/Shared/Pagination.ascx", new Mvc2.Views.Shared.PaginationViewData()
{
PageIndex = ViewData.EntryList.PageIndex,
TotalPages = ViewData.EntryList.TotalPages,
PageActionLink = Url.Action("List","Entry", new { category = ViewData.Category, page = "{page}"}),
TotalCount = ViewData.EntryList.TotalCount,
PageSize = ViewData.EntryList.PageSize
}, null)%>
The properties of the control and of the PagedList are almost the same – only the "PageActionLink" is a specific property. The "PageActionLink" is the action Link to your controller – "/Management/Tag/2" route to your "Management"-Controller and "Tag"-ActionMethod with the page parameter. The "page = {page}" parameter is only a template for the real page number, which will be replaced in my control:
<li><a href="<%=ViewData.PageActionLink.Replace("%7Bpage%7D", page.ToString())%>"><%=page.ToString()%></a></li>
The URL helper method encode the { and } to %7B and %7D. I can´t explain it very well in english – one quick look in the source code (pagination.ascx) is very helpful
Feel free to use it.
PS: English blogging is hard :/



Troy Goode
April 9, 2008
Nice work, Robert. This is something I (and I’m sure many other MVC developers) will use often.
Oh, and your English was fine. =)
Troy Goode
April 9, 2008
Oh, and on another note, coincidentally I have made the same changes to Rob’s PagedList class as you have, but I think this is a bit better of a calculation for TotalPages:
(excuse the formatting please)
if( this.TotalCount > 0 )
{
this.TotalPages = (int)Math.Ceiling( (double)this.TotalCount / (double)this.PageSize );
}
else
{
this.TotalPages = 0;
}
anonymous
June 1, 2008
Can you post your controller code to complete this blog post so we can see how you are interacting with that. Sure, I can “imagine” sort of what you’re doing such as adding a page param in your action like you said, and imagine up your controller based on your route but would like to see the actual action, so I have a little more clear context.
Would be a big help.
CK1
June 5, 2008
Just wanted to say thanks – I’m new to MVC and this was a great help for paging! Cheers!
Robert Muehsig
June 5, 2008
The controller code:
You just have to pass a PagedList to your Viewdata like that:
ListViewData list = new ListViewData();
list.EntryList = EntryManager.LoadEntryCollectionByCategory(category).ToPagedList(page ?? 1);
Hope this helps
Paul Linton
June 10, 2008
I think that when you changed your page numbers to have a base of one rather than zero you need to change HasNextPage to be
get { return (PageIndex * PageSize) < TotalCount; }
Eg change <= to <
Marco Castro
June 30, 2008
I’m trying with MVC Preview 3 but at the view form the system do not find ViewData.EntryList. Where is it?
Robert Muehsig
July 1, 2008
You need a strongly typed ViewData class – EntryList is just a sample property in this ViewDataClass.
Here is a nice blogpost about strongly typed ViewData classes:
http://blog.codeville.net/2008/02/21/aspnet-mvc-making-strongly-typed-viewpages-more-easily/
Rui Heh
July 1, 2008
Hi there, great code!!! Just want to address one small issue, when pages exceeds the default total page and next is clicked, it won’t show the next set of pages.
Here is what I did. Hope if someone else has the same problem can make use of it.
public int StartIndex
{
get
{
if (PageIndex > TotalPages)
{
return PageIndex – (PageIndex % TotalPages) + 1;
}
else
return 1;
}
}
and then, change the for loop to
for (int page = ViewData.Model.StartIndex; page <= (ViewData.Model.StartIndex + ViewData.Model.TotalPages – 1); page++)
If it is still not cleared. Email me royheh@comcast.net
Jahedur Rahman
July 11, 2008
Nice Blog.
gonzalo
January 7, 2009
Hi, I’m having a hard time trying to find the RenderUserControl function.
It’s not in HtmlHelper class
Cheers
Robert Muehsig
January 7, 2009
The “RenderUserControl” was in the Beta 3 days – maybe it has be renamed or you can find it in the MVCFuture bits (download @ codeplex.com/aspnet ).
gonzalo
January 8, 2009
I finally found the solution. It’s called RenderPartial now. It takes the control name and ViewData as arguments.
Thanks for answering!
Gonzalo
Craig
January 9, 2009
PagedList can use IEnumerable instead of IQueryable (more generic). Cheers!!
Craig
January 9, 2009
Nevermind, I see the benefit of having an IQueryable ctor, but IEnumerable is still a good option to have
Buona
February 6, 2009
Love the advice. Thank you.
Josh
May 7, 2009
Hello, I have a question about what my view page should inherit from. Im getting the following error:
Parser Error Message: ‘Mvc2.Views.Shared.Pagination’ is not allowed here because it does not extend class ‘System.Web.Mvc.ViewPage’.
Source Error:
Line 1: <%@ Page Title="List Checkups" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="Mvc2.Views.Shared.Pagination" %>
Line 2:
Line 3: <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Is there something I am leaving out? Ive added the Inherits=”Mvc2.Views.Shared.Pagination” At the top of my page, yet I still get this error. I am new to MVC. I would really like to get this working. Thanks for any help!
Nisar Khan
June 30, 2009
can anybody post the sample downloadble code for testing? please?
thanks.
Stefano
August 6, 2009
please … link a downloadble example thanks
paolo izmoto
August 20, 2009
Hello,
This is very useful stuff.
Thanks.
j
August 29, 2009
I’m very new to mvc. do you have a “test” solution that you can post? thanks!
ritz
November 17, 2009
hello,
i m not getting the viewdata on the user control,please tell me from where can I get this,but the post is good
Tho ta
December 18, 2009
Everybody for me source sample of this topic?
I very need source sample.
Email: tavtho@gmail.com
please?
thank!!!
Robert
January 1, 2010
Leiber Robert – Vielen Dank fuer deine Poste! Jawohl ist Blogging auf Englisch sehr schwer!
Slongia
January 20, 2010
Leaning ASP.NET MVC 2. Will appreciate if you post a link of working solution for download.
Webdiyer
February 8, 2010
I wrote a free asp.net mvc paging component called MvcPager,it support both basic url paging and Ajax paging using jQuery or MicrosoftAjax script library,you can view online demo and download a copy from http://en.webdiyer.com .
Moshe Dubman
February 17, 2010
Thank you, I will be using this in my next project
Vielen Dank und gruss aus Israel
Moshe
Webdiyer
February 24, 2010
I wrote a free asp.net mvc paging component called MvcPager,it has more features and support Ajax paging using MicrosoftAjax or jQuery script library,you can view online demo and download it from http://en.webdiyer.com/mvcpager
ibuzzs
August 18, 2010
I’m learning mvc, it very nice tutorial, thanks!
Ragims
August 27, 2010
I dont understand how it works in controller.
Can you please explain what you meen with:
ListViewData list = new ListViewData();
list.EntryList = EntryManager.LoadEntryCollectionByCategory(category).ToPagedList(page ?? 1);
Thanks a lot and take care,
Ragims
Mike
November 26, 2010
Hi Robert,
please share your code !
Carlos
June 26, 2011
Don’t forget the css please , some people will like to have the css too.
.
But this is great stuff by the way
Example Code
June 29, 2011
Do you send for me example code ? Thanks you
mac keylogger
July 12, 2011
You have hit the mark. In it something is also to me your idea is
pleasant. I suggest to take out for the general discussion.