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:

image

image

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

image 

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"…

image

…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 :)

2 Kommentare bisher »

  1. Code-Inside gibts jetzt auch auf englisch… | Code-Inside Blog sagt

    am 9. April 2008 @ 06:54

    [...] ASP.NET MVC – Pagination View User ControlCode-Inside International: ASP.NET MVC – Pagination View User [...]

  2. ASP.NET MVC - Resources | Code-Inside Blog sagt

    am 25. April 2008 @ 06:31

    [...] Sogar mein Pagination User Control ist dabei [...]

Komentar RSS · TrackBack URI

Hinterlasse einen Kommentar

Name: (erforderlich)

eMail: (erforderlich)

Website:

Kommentar: