ASP.NET MVC – Pagination View User Control
Bereits hier habe ich über das Paging geschrieben – da dieses Feature eigentlich auf fast allen Seiten irgendwie benutzt wird, musste ich dies kapseln.
Beispiel dafür:
Vorteile wenn man das in einem Control bündelt:
- Design ist gleich
- Änderungen können zentral eingespielt werden
Für das Design könnte man sich hier Inspiration holen.
Dateistruktur
Es ist ein einfaches 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()
{
}
}
}
Die PaginationViewData Klasse kapselt am Ende nur die Daten – streng typisierte ViewDatas.
Anwendung – Helper "PagedList"
Die Anwendung des Controls ist recht einfach gestaltet, insbesondere wenn man bereits diese "PagedList" Klasse als Typ in seinem ViewData benutzt:
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);
}
}
}
Das Original stammt von Rob Conery – ich habe daran nur verändert, dass zuerst die "Seite 1" zu sehen ist – weil eine "Seite 0" würde am Ende die Nutzer nur verwirren.
Anwendung – Im View
In unserem View (in dem das Control dargestellt werden soll) bauen wir das über den Html.RenderUserControl recht simpel ein:
<%=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)%>
Hier übergeben wir jetzt die "Zustandsdaten" von unserem View dem Control. Ein wichtiger Punkt ist der "PageActionLink". Dieser Link ruft am Ende wieder den Controller auf – z.B. den Link "/Management/Tag/2" würde meinen "Management"-Controller aufrufen und dort die "Tag"-Action mit der entsprechenden Seitenanzahl. Da diese Anzeige mit "1", "2", "3"…
…dynamisch erstellt wird, dient der {page} Parameter hier als Template. Was später durch die einzelnen Seiten ersetzt wird:
<li><a href="<%=ViewData.PageActionLink.Replace("%7Bpage%7D", page.ToString())%>"><%=page.ToString()%></a></li>
"%7B" steht dabei für { und "%7D" für } – der URL Helper maskiert diese Zeichen so.
Einfach in den Quellcode des Controls schauen – dann ergibt es einen Sinn
Ich werde mein Beispiel demnächst mal in einer Beta veröffentlichen – dann kann man das ganze auch in Aktion sehen. Ansonsten sind alle wesentlichen Klassen in diesem Post aufgeführt







Letzte Kommentare