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