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 :/ ;)