quarta-feira, 22 de setembro de 2010

MVC - Paginacao

Fala galera,
Hoje irei mostrar como fazer uma paginação em uma tabela no MVC, pois é tem que ser feita na mão adeus ao GridView.

Bom vamos la.

Obs: Neste exemplo estou usando Entity Framework, no final usarei um objeto do EF, se usar outro tipo de persistencia somente altere o objeto para uma lista do seu objeto (List<SeuObj>).

Primeiro vamos modificar o global.asax, incluindo uma nova rota.
 Dentro do método RegisterRoutes, deixando ele assim:

public static void RegisterRoutes(RouteCollection routes)
{
 routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 routes.MapRoute(
  "Paginacao",                                            // Route name
  "{controller}/{page}",                                  // URL with parameters
  new { action = "Index" }                                // Parameter defaults
 );
 routes.MapRoute(
  "Default",                                              // Route name
  "{controller}/{action}/{id}",                           // URL with parameters
  new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
 );
}

Certo ele auxiliara mais a frente quando chamarmos o link da paginação.

Proximo passo é criar a classe de paginação, ficará assim:

public class PaginatedList<T> : List<T>
    {
        public int PageIndex { get; private set; }
        public int PageSize { get; private set; }
        public int TotalCount { get; private set; }
        public int TotalPages { get; private set; }
        public string Controller { get; private set; }
        public string Action { get; private set; }

        public PaginatedList(IEnumerable<T> source, int pageIndex, int pageSize, string controller)
        {
            Add(source, pageIndex, pageSize, controller, string.Empty);
        }

        public PaginatedList(IEnumerable<T> source, int pageIndex, int pageSize, string controller, string action)
        {
            Add(source, pageIndex, pageSize, controller, action);
        }

        void Add(IEnumerable<T> source, int pageIndex, int pageSize, string controller, string action)
        {
            PageIndex = pageIndex;
            PageSize = pageSize;
            TotalCount = source.Count();
            TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);
            Controller = controller;
            Action = action;
            this.AddRange(source.Skip(PageIndex * PageSize).Take(PageSize));
        }

        public bool HasPreviousPage
        {
            get
            {
                return (PageIndex > 0);
            }
        }

        public bool HasNextPage
        {
            get
            {
                return (PageIndex + 1 < TotalPages);
            }
        }

        public void Paginacao()
        {
            HttpResponse response = HttpContext.Current.Response;
            if (string.IsNullOrEmpty(Action))
            {
                if (HasPreviousPage)
                    response.Write(string.Format("<a href='/{0}/{1}'>{2}</a>", Controller, PageIndex - 1, "<<<"));
                if (HasNextPage)
                    response.Write(string.Format("<a href='/{0}/{1}'>{2}</a>", Controller, PageIndex + 1, ">>>"));
            }
            else
            {
                if (HasPreviousPage)
                    response.Write(string.Format("<a href='/{0}/{1}/{2}'>{3}</a>", Controller, Action, PageIndex - 1, "<<<"));
                if (HasNextPage)
                    response.Write(string.Format("<a href='/{0}/{1}/{2}'>{3}</a>", Controller, Action, PageIndex + 1, ">>>"));
            }
        }
    }
Após criar essa classe ja temos um novo retorno de Model para nossa view.
Em nossa aspx, no caso estou utilizando a index.aspx para listar as informações devemos mudar o inherits da pagina da seguinte forma.

Inherits="System.Web.Mvc.ViewPage<HelloMVC.MVC.Controllers.PaginatedList<HelloMVC.MVC.Models.TB_Usuario>>"

Reparem que na ViewPage ao invez de eu passar como generics type IEnumerable, estou passando nossa classe PaginatedList, lembrando que deve passar corretamente o caminho senao temos o seguinte erro:












Após a modificação deverá funcionar a página, com tudo funcionando iremos atribuir a paginação na página.

Então vamos ao nosso aspx novamente e iremos chamar um método que está na nossa classe de paginação, devendo ficar assim:

    </table>
    <% Model.Paginacao(); %>

Eu coloquei abaixo da table, porém fica ao seu critério.

Enfim vamos ao nosso controller da página

No método Index iremos fazer uma pequena modificação:


public ActionResult Index(int? page)
{
    ViewData.Model = new PaginatedList<TB_Usuario>(usu, page ?? 0, 2, "Usuario");

    return View();
}

Essa modificação devemos passar o objeto que retornará na lista por parâmetro genérico <TB_Usuario> e a lista db.TB_Usuario como primeiro parâmetro.
O terceiro parâmetro é o controller usado.
Podendo também incluir um parâmetro a mais para passar o action, se utilizarmo esse contrutor com action temos que criar uma nova rota no global.asax

Com tudos parâmetros sendo atribuidos corretamente é só rodar o projeto e sua paginação estará funcionando.

Até o proximo.

Nenhum comentário:

Postar um comentário