sábado, 22 de octubre de 2011

Ordernar, filtrar y pagineo (MVC)

Para este ejemplo usaremos la tabla products de la base de datos northwind y ya debemos de tener su controlador y las vistas del mismo.  (Ver ejemplo anterior)

Código inicial del contraldor:

public ViewResult Index() 
{ 
    var products = db.Products.Include(p => p.Categories).Include(p => p.Suppliers);
    return View(products.ToList()); 
}
Código inicial de la vista:
<table> 
    <tr> 
        <th> 
            ProductName 
        </th> 
        <th> 
            Suppliers 
        </th> 
        <th> 
            Categories 
        </th> 
        <th> 
            UnitPrice 
        </th> 
        <th> 
            UnitsInStock 
        </th> 
        <th> 
            Discontinued 
        </th> 
        <th></th> 
    </tr>
Sort:
En este ejemplo agregaremos al controlador.

public ViewResult Index(string sortOrder)
{ 
  ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "ProductName desc" : ""; 
  ViewBag.UnitPriceSortParm = sortOrder == "UnitPrice" ? "UnitPrice desc" : "UnitPrice"; 

  var products = db.Products.Include(p => p.Categories).Include(p => p.Suppliers);

   switch (sortOrder) 
   { 
   case "ProductName desc": 
       products = products.OrderByDescending(s => s.ProductName); 
       break; 
   case "UnitPrice": 
       products = products.OrderBy(s => s.UnitPrice); 
       break; 
   case "UnitPrice desc": 
        products = products.OrderByDescending(s => s.UnitPrice); 
        break; 
   default: 
        products = products.OrderBy(s => s.ProductName); 
        break; 
    } 
   return View(products.ToList()); 
}


En la vista cambiaremos los header por links los cuales enviaran el orden necesario:


<table> 
    <tr> 
        <th>             
 @Html.ActionLink("Product Name", "Index", new { sortOrder = ViewBag.NameSortParm }) 
        </th> 
        <th> 
            Suppliers 
        </th> 
        <th> 
            Categories 
        </th> 
        <th> 
@Html.ActionLink("UnitPrice", "Index", new { sortOrder = ViewBag.UnitPriceSortParm }) 
        </th> 
        <th> 
            UnitsInStock 
        </th> 
        <th> 
            Discontinued 
        </th> 
        <th></th> 
    </tr>

Resultado:



Filtros:
En este ejemplo agregaremos al controlador.


public ViewResult Index(string sortOrder, string searchString)
{ 
  ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "ProductName desc" : ""; 
  ViewBag.UnitPriceSortParm = sortOrder == "UnitPrice" ? "UnitPrice desc" : "UnitPrice"; 
  
  ViewBag.SearchString = searchString;
  var products = db.Products.Include(p => p.Categories).Include(p => p.Suppliers);

if (!String.IsNullOrEmpty(searchString)) 
{ 
  products = products.Where(s => s.ProductName.ToUpper().Contains(searchString.ToUpper()));
                                        
} 

   switch (sortOrder) 
   { 
   case "ProductName desc": 
       products = products.OrderByDescending(s => s.ProductName); 
       break; 
   case "UnitPrice": 
       products = products.OrderBy(s => s.UnitPrice); 
       break; 
   case "UnitPrice desc": 
        products = products.OrderByDescending(s => s.UnitPrice); 
        break; 
   default: 
        products = products.OrderBy(s => s.ProductName); 
        break; 
    } 
   return View(products.ToList()); 
}



En la vista agregaremos un textbox necesario para buscar los productos:

<p> 
    @Html.ActionLink("Create New", "Create") 

    @using (Html.BeginForm()) 
    { 
        <p> 
            Product Name: @Html.TextBox("SearchString") &nbsp; 
            <input type="submit" value="Search" /></p> 
    } 

</p>

En la vista también debemos de cambiar los action link para conservar el valor del searchString.

 @Html.ActionLink("Product Name", "Index", new { sortOrder = ViewBag.NameSortParm, 
                SearchString = ViewBag.SearchString }) 

@Html.ActionLink("UnitPrice", "Index", new { sortOrder = ViewBag.UnitPriceSortParm,                     SearchString = ViewBag.SearchString })


Resultado:



Pagineo:
Antes que nada tenemos que instalar : PagedList NuGet Package.


  1. Menu Tools
  2. Library Package Manager
  3. Add Library Package Reference
  4. Clic en online en la parte izquierda
  5. Luego en buscar escriba PagedList
  6. Por ultimo instale el paquete.
Se agrega la libreria el siguiente using:

using PagedList;

Código del controlador:

public ViewResult Index(string sortOrder, string currentFilter,
string searchString, int? page) 
{ 
    ViewBag.CurrentSort = sortOrder; 
    ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "ProductName desc" : ""; 
    ViewBag.UnitPriceSortParm = sortOrder == "UnitPrice" ? "UnitPrice desc" : "UnitPrice"

    ViewBag.SearchString = searchString;

    if (Request.HttpMethod == "GET") 
    { 
        searchString = currentFilter; 
    } 
    else 
    { 
        page = 1; 
    } 
    ViewBag.CurrentFilter = searchString; 

    var products = db.Products.Include(p => p.Categories).Include(p => p.Suppliers); 

    if (!String.IsNullOrEmpty(searchString)) 
    { 
 products = products.Where(s => s.ProductName.ToUpper().Contains(searchString.ToUpper()));
                                        
    } 

    switch (sortOrder) 
    { 
        case "ProductName desc": 
            products = products.OrderByDescending(s => s.ProductName); 
            break; 
        case "UnitPrice":
            products = products.OrderBy(s => s.UnitPrice); 
            break; 
        case "UnitPrice desc": 
            products = products.OrderByDescending(s => s.UnitPrice); 
            break; 
        default: 
            products = products.OrderBy(s => s.ProductName); 
            break; 
    } 

    int pageSize = 10; 
    int pageIndex = (page ?? 1);
    return View(products.ToPagedList(pageIndex, pageSize)); 
}

Código de la vista:
Debemos de cambiar el model:

@model PagedList.IPagedList<Northwind.Models.Products>

Agregar el siguiente código al final de la tabla:

<div> 
    Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber)
    of @Model.PageCount 
    &nbsp; 
    @if (Model.HasPreviousPage) 
    { 
        @Html.ActionLink("<<", "Index", new { page = 1, 
sortOrder = ViewBag.CurrentSort,
currentFilter = ViewBag.CurrentFilter, 
SearchString = ViewBag.SearchString })

        @Html.Raw("&nbsp;"); 
        @Html.ActionLink("< Prev", "Index", new { page = Model.PageNumber - 1,
sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter, 
SearchString = ViewBag.SearchString })
    } 
    else 
    { 
        @:<< 
        @Html.Raw("&nbsp;"); 
        @:< Prev 
    } 
    &nbsp; 
    @if (Model.HasNextPage) 
    { 
        @Html.ActionLink("Next >", "Index", new {      page = Model.PageNumber + 1,
sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter, 
SearchString = ViewBag.SearchString })

        @Html.Raw("&nbsp;"); 
        @Html.ActionLink(">>", "Index", new { page = Model.PageCount,
sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter, 
SearchString = ViewBag.SearchString })
    } 
    else 
    { 
        @:Next > 
        @Html.Raw("&nbsp;") 
        @:>> 
    } 
</div>


Resultado:








6 comentarios:

ruben chable matu dijo...

Muchas gracias por la informacion se me hizo muy util gracias.

Daniel Alberto Martínez dijo...

Gracias por todo, si me ayudó mucho pero el paginado no me queda no me reconoce en la vista el PagedList :(

Carlos Juan dijo...

Daniel:

Llena la tabla con jquery, mira este ejemplo.

http://www.cjorellana.net/2015/04/mvc-grid-jquery.html

Carlos Juan dijo...
Este comentario ha sido eliminado por el autor.
Carlos Juan dijo...
Este comentario ha sido eliminado por el autor.
Mike guachoski dijo...

Una preguntota, como se le puede hacer para exportar a excel los datos filtrados