Created
July 5, 2013 09:46
-
-
Save takemyoxygen/5933406 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Collections.Specialized; | |
using System.Linq; | |
using System.Text; | |
using System.Web; | |
using System.Web.Mvc; | |
namespace MvcPager.Html | |
{ | |
public static class PagingEx | |
{ | |
private class PageLinkInformation | |
{ | |
public string Text { get; private set; } | |
public int Index { get; private set; } | |
public PageLinkInformation(string text, int index) | |
{ | |
Index = index; | |
Text = text; | |
} | |
} | |
/// <summary> | |
/// Renders a set of links represenging a paging control | |
/// </summary> | |
/// <param name="htmlHelper"><see cref="HtmlHelper"/> instance</param> | |
/// <param name="itemsPerPage">Number of items that are displayed on one page</param> | |
/// <param name="totalItems">Total items that are displayed across all the pages</param> | |
/// <param name="currentPage">1-based index of the current page</param> | |
/// <param name="linkCssClass">CSS class that will be applied to all paging links. No class if empty</param> | |
/// <param name="numericListsCount">Max. count of numeric links that will be displyaed</param> | |
/// <param name="lastPageText">Text of the link to the last page. If null or empty then link to the last page won't be displayed</param> | |
/// <param name="firstPageText">Text of the link to the first page. If null or empty then link to the first page won't be displayed</param> | |
/// <param name="nextPageText">Text of the link to the next page which is not presented as numeric link</param> | |
/// <param name="previousPageText">Text of the link to the previous page which is not presented as numeric link</param> | |
/// <param name="pageIndexQueryStringParameter">Name of the query string parameter that stores current page index</param> | |
/// <returns></returns> | |
public static MvcHtmlString Paging( | |
this HtmlHelper htmlHelper, | |
int itemsPerPage, | |
int totalItems, | |
int currentPage = 0, | |
string linkCssClass = null, | |
int numericListsCount = 10, | |
string lastPageText = null, | |
string firstPageText = null, | |
string nextPageText = ">", | |
string previousPageText = "<", | |
string pageIndexQueryStringParameter = "Page") | |
{ | |
int pagesCount = totalItems/itemsPerPage; | |
if (totalItems%itemsPerPage != 0) pagesCount++; | |
if (currentPage == 0) | |
{ | |
if (!int.TryParse(HttpContext.Current.Request.QueryString[pageIndexQueryStringParameter], | |
out currentPage)) | |
{ | |
currentPage = 1; | |
} | |
} | |
int[] numericLinks = NumericLinks(currentPage, pagesCount, numericListsCount); | |
bool insertFirstPageLink = !string.IsNullOrEmpty(firstPageText) && | |
numericLinks[0] != 1; | |
bool insertLastPageLink = !string.IsNullOrEmpty(lastPageText) && | |
numericLinks.Last() != pagesCount; | |
bool insertNextPageLink = numericLinks.Last() < pagesCount - 1; | |
bool insertPrevPageLink = numericLinks[0] > 2; | |
var pages = new List<PageLinkInformation>(numericLinks.Length + 4); // 4 additional links are "First", "<<", ">>" and "Last" | |
if (insertFirstPageLink) pages.Add(new PageLinkInformation(firstPageText, 1)); | |
if (insertPrevPageLink) pages.Add(new PageLinkInformation(previousPageText, numericLinks[0] - 1)); | |
pages.AddRange(numericLinks.Select(i => new PageLinkInformation(i.ToString(), i))); | |
if (insertNextPageLink) pages.Add(new PageLinkInformation(nextPageText, numericLinks.Last() + 1)); | |
if (insertLastPageLink) pages.Add(new PageLinkInformation(lastPageText, pagesCount)); | |
return MvcHtmlString.Create(RenderHtml(pages, linkCssClass, currentPage, pageIndexQueryStringParameter)); | |
} | |
private static int[] NumericLinks(int currentPage, int pagesCount, int desiredLinksCount) | |
{ | |
int actualLinksCount = Math.Min(desiredLinksCount, pagesCount); | |
int desiredNumberOfLinksAfterCurrent = (actualLinksCount + 1)/2; | |
int actualNumberOfLinksAfterCurrent = Math.Min(pagesCount, desiredNumberOfLinksAfterCurrent + currentPage) - | |
pagesCount; | |
int desiredNumberOfLinksBeforeCurrent = actualLinksCount - actualNumberOfLinksAfterCurrent - 1; | |
int actualNumberOfLinksBeforeCurrent = Math.Min(desiredNumberOfLinksBeforeCurrent, currentPage - 1); | |
int firstNumericLink = currentPage - actualNumberOfLinksBeforeCurrent; | |
return Enumerable | |
.Range(firstNumericLink, actualLinksCount) | |
.ToArray(); | |
} | |
private static string RenderHtml( | |
IEnumerable<PageLinkInformation> links, | |
string cssClass, | |
int currentPage, | |
string pageIndexQueryStringParameter) | |
{ | |
return string.Concat(links | |
.Select(link => | |
{ | |
if (currentPage == link.Index) return link.Text; | |
var a = new TagBuilder("a") {InnerHtml = link.Text}; | |
a.MergeAttribute("href", GetPageUrl(link.Index, pageIndexQueryStringParameter)); | |
if (!string.IsNullOrEmpty(cssClass)) a.AddCssClass(cssClass); | |
return a.ToString(); | |
})); | |
} | |
private static string GetPageUrl(int pageIndex, string pageQueryStringParameter) | |
{ | |
var queryString = new NameValueCollection(HttpContext.Current.Request.QueryString); | |
queryString.Set(pageQueryStringParameter, pageIndex.ToString()); | |
var sb = new StringBuilder(HttpContext.Current.Request.Path); | |
sb.Append("?"); | |
for (int i = 0; i < queryString.Count; i++) | |
{ | |
if (i > 0) | |
{ | |
sb.Append("&"); | |
} | |
sb.Append(HttpUtility.UrlEncode(queryString.Keys[i])); | |
sb.Append("="); | |
sb.Append(HttpUtility.UrlEncode(queryString[i])); | |
} | |
return sb.ToString(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment