[ASP.NET MVC] Mostrar datos paginados en un Datagrid I

Siguiendo la línea de Scott Mitchell en sus últimos artículos, a lo largo de una serie de posts vamos a ir viendo como podemos mostrar nuestros datos en formato datagrid, y como podemos aplicar las funcionalidades de paginado, filtrado y orden sobre los mismos, dentro de una aplicación ASP.NET MVC. En el artículo de hoy vamos a ver el primero de los casos, para ello creamos un proyecto de tipo ASP.NET MVC 2 Web Application que llamaremos DataGridApp. En el, añadimos la base de datos AdventureWorks, ya que tiene un gran número de tablas y registros con los que poder trabajar, y aplicarles la funcionalidad específica.

A continuación creamos un modelo de tipo LINQ to SQL Classes llamado StoreModel, que contendrá las tablas Customer y Store, de forma que nuestro modelo quede de la siguiente forma:

image

 

A continuación creamos un controlador especifico para trabajar con el modelo creado, y al que llamaremos StoreController.

image

En dicho controlador

1.Añadimos la referencia a nuestro modelo, y la referencia a Linq para poder trabajar con ellos:

  1. using DataGridApp.Models;
  2. using System.Data.Linq;

2.Inicializamos el contexto de nuestro modelo:

  1. StoreModelDataContext context = new StoreModelDataContext();

 

3.Creamos la acción Index, cuyo código será el siguiente:

  1. public ActionResult Index()
  2. {
  3.     return View(context.Stores);
  4. }

Y su vista correspondiente, de forma que podamos mostrar todos los elementos definidos en nuestro contexto de datos. Para ello hacemos clic con él botón derecho sobre Index y añadimos una vista con las siguientes propiedades:

image

En dicha vista, cambiamos la propiedad Inherits a:

System.Web.Mvc.ViewPage<IEnumerable<DataGridApp.Models.Store>>

Y dentro del contenedor principal añadimos el siguiente código:

  1. <table>
  2.         <tr>
  3.             <th>Store Name</th>
  4.             <th>Cust. Acc. Number</th>
  5.             <th>Sales Person ID</th>
  6.         </tr>
  7.  
  8.     <% foreach (var item in Model) { %>
  9.     
  10.         <tr>
  11.             <td><%: item.Name %></td>
  12.             <td><%: item.Customer.AccountNumber %></td>
  13.             <td><%: item.SalesPersonID %></td>
  14.         </tr>
  15.     
  16.     <% } %>
  17.  
  18.     </table>

A continuación creamos una clase para definir el modelo específico que queremos mostrar mediante la acción Paged. Para ello hacemos clic con el botón derecho sobre la carpeta Models y añadimos una clase llamada StoreGridModel que contendrá el siguiente código:

  1. public class StoreGridModel
  2.     {
  3.  
  4.         // Definimos las propiedades
  5.         public IEnumerable<Store> Stores { get; set; }
  6.         public int CurrentPageIndex { get; set; }
  7.         public int PageSize { get; set; }
  8.         public int TotalRecordCount { get; set; }
  9.         public int NumericPageCount { get; set; }
  10.         public int PageCount
  11.         {
  12.             get
  13.             {
  14.                 return this.TotalRecordCount / this.PageSize;
  15.             }
  16.         }
  17.         public StoreGridModel()
  18.         {
  19.  
  20.             // Establecemos los valores por defecto
  21.             this.PageSize = 10;
  22.             this.NumericPageCount = 10;
  23.         }
  24.  
  25.     }

Por último pasamos a definir la acción Paged, a través de la cual mostraremos nuestros elementos paginados en grupos de 10 en 10, y por los que podremos navegar mediante el uso de vistas parciales. El código que utilizamos para implementar dicha acción es el siguiente:

  1. public ActionResult Paged(int page = 1, int pageSize = 10)
  2.         {
  3.             var model = new  StoreGridModel
  4.             {
  5.                 CurrentPageIndex = page,
  6.                 PageSize = pageSize
  7.             };
  8.  
  9.             // Se determina el numero total de “stores” que se muestran en cada página
  10.             model.TotalRecordCount = context.Stores.Count();
  11.             // Se obtiene la página actual de “stores”
  12.  
  13.             model.Stores = context.Stores
  14.                            .Skip((model.CurrentPageIndex – 1) * model.PageSize)
  15.                            .Take(model.PageSize);
  16.  
  17.             return View(model);
  18.         }

 

Definimos su vista correspondiente, que tendrá las siguientes propiedades:

image

Y cuyo código será el siguiente:

  1. <p>
  2.         <i>Estas viendo la página <%: Model.CurrentPageIndex %> de <%: Model.PageCount %></i>
  3.     </p>
  4.     <table>
  5.         <tr>
  6.             <th>Store Name</th>
  7.             <th>Cust. Acc. Number</th>
  8.             <th>Sales Person ID</th>
  9.         </tr>
  10.  
  11.     <% foreach (var item in Model.Stores) { %>
  12.     
  13.         <tr>
  14.             <td><%: item.Name %></td>
  15.             <td><%: item.Customer.AccountNumber %></td>
  16.             <td><%: item.SalesPersonID %></td>
  17.         </tr>
  18.     
  19.     <% } %>
  20.  
  21.         <tr>
  22.             <td colspan=”5″>
  23.                 <% Html.RenderPartial(“Pager”, Model); %>
  24.             </td>
  25.         </tr>
  26.  
  27.     </table>

Para que dicha vista funcione correctamente es necesario implementar previamente dos vistas parciales que guardaremos en la carpeta Views/Shared.

La primera de ellas, Pager.ascx nos permitirá realizar el renderizado parcial de los elementos de nuestro modelo, y en ella definiremos los distintos elementos de navegación. Esta vista se crea con las siguientes propiedades:

image

Y cuyo código es el siguiente:

  1. <div class=”pager”>
  2. <%
  3.     // Creamos el Link “Anterior”
  4.     Html.RenderPartial(“PagerLink”, Model, new ViewDataDictionary { { “Text”, “<< Anterior” }, { “PageIndex”, Model.CurrentPageIndex – 1 }, { “Selected”, false }, { “Inactive”, Model.CurrentPageIndex == 1 } });
  5.  
  6.     
  7.     // Creamos los links númericos    
  8.     var startPageIndex = Math.Max(1, Model.CurrentPageIndex – Model.NumericPageCount / 2);
  9.     var endPageIndex = Math.Min(Model.PageCount, Model.CurrentPageIndex + Model.NumericPageCount / 2);
  10.  
  11.     // Mostramos los valores iniciales
  12.     if (Model.PageCount > Model.NumericPageCount / 2)
  13.     {
  14.         if (startPageIndex > 1)
  15.             Html.RenderPartial(“PagerLink”, Model, new ViewDataDictionary { { “Text”, “1” }, { “PageIndex”, 1 }, { “Selected”, false }, { “Inactive”, false } });
  16.         if (startPageIndex > 2)
  17.             Html.RenderPartial(“PagerLink”, Model, new ViewDataDictionary { { “Text”, “2” }, { “PageIndex”, 2 }, { “Selected”, false }, { “Inactive”, false } });
  18.         if (startPageIndex > 3)
  19.             Html.RenderPartial(“PagerLink”, Model, new ViewDataDictionary { { “Text”, “…” }, { “PageIndex”, 1 }, { “Selected”, false }, { “Inactive”, true } });
  20.     }
  21.  
  22.     // Añadimos el resto de páginas numericas
  23.     for (var i = startPageIndex; i <= endPageIndex; i++)
  24.         Html.RenderPartial(“PagerLink”, Model, new ViewDataDictionary { { “Text”, i }, { “PageIndex”, i }, { “Selected”, i == Model.CurrentPageIndex }, { “Inactive”, false } });
  25.  
  26.     
  27.     // Mostramos los valores finales
  28.     if (Model.PageCount > Model.NumericPageCount / 2)
  29.     {
  30.         if (endPageIndex < Model.PageCount – 2)
  31.             Html.RenderPartial(“PagerLink”, Model, new ViewDataDictionary { { “Text”, “…” }, { “PageIndex”, 1 }, { “Selected”, false }, { “Inactive”, true } });
  32.         if (endPageIndex < Model.PageCount – 1)
  33.             Html.RenderPartial(“PagerLink”, Model, new ViewDataDictionary { { “Text”, Model.PageCount – 1 }, { “PageIndex”, Model.PageCount – 1 }, { “Selected”, false }, { “Inactive”, false } });
  34.         if (endPageIndex < Model.PageCount)
  35.             Html.RenderPartial(“PagerLink”, Model, new ViewDataDictionary { { “Text”, Model.PageCount }, { “PageIndex”, Model.PageCount }, { “Selected”, false }, { “Inactive”, false } });
  36.     }
  37.  
  38.     // Creamos el link “Siguiente”
  39.     Html.RenderPartial(“PagerLink”, Model, new ViewDataDictionary { { “Text”, “Siguiente >>” }, { “PageIndex”, Model.CurrentPageIndex + 1 }, { “Selected”, false }, { “Inactive”, Model.CurrentPageIndex == Model.PageCount } });
  40. %>
  41. </div>

Y la segunda PagerLink.ascx que nos permitirá navegar por las distintas vistas, y aplicarles los estilos específicos. Esta contará con las siguientes propiedades:

image

Y su código es el siguiente:

  1. <%
  2.     if ((bool)ViewData[“Inactive”])
  3.     {
  4.         Response.Write(string.Format(“<span class=”{0}”>{1}</span>”, “pagerButtonDisabled”, ViewData[“Text”]));
  5.     }
  6.     else
  7.     {
  8.         var routeData = new RouteValueDictionary { { “page”, ViewData[“PageIndex”].ToString() }, { “pageSize”, Model.PageSize } };
  9.         var htmlAttributes = new Dictionary<string, object>();
  10.         if ((bool)ViewData[“Selected”])
  11.             htmlAttributes.Add(“class”, “pagerButtonCurrentPage”);
  12.         else
  13.             htmlAttributes.Add(“class”, “pagerButton”);
  14.  
  15.         Response.Write(
  16.             Html.ActionLink(
  17.                     ViewData[“Text”].ToString(),                                    // Link Text
  18.                     Html.ViewContext.RouteData.Values[“action”].ToString(),         // Acción
  19.                     Html.ViewContext.RouteData.Values[“controller”].ToString(),     // Controlador
  20.                     routeData,                                                      // Ruta
  21.                     htmlAttributes                                                  // Atributos HTML para aplicar a los hipervinculos
  22.                 ).ToHtmlString()
  23.         );
  24.     }
  25. %>

Creamos las clases que vamos a aplicar para personalizar el formato del paginado dentro de la hoja de estilos Site.css:

  1. /*Customizations*/
  2.  
  3. td.pager {
  4.     background-color: #eee;
  5. }
  6.  
  7. td.pager div {
  8.     font-size: smaller;
  9.     font-weight: bold;
  10.     padding: 5px;
  11. }
  12.  
  13. a.pagerButton, a.pagerButton:visited
  14. {
  15.     border: solid 1px #eee;
  16.     padding: 4px;
  17.     text-decoration: none;
  18.     color: #006;
  19.     margin: 0px 2px 0px 2px;
  20. }
  21.  
  22. a.pagerButton:hover
  23. {
  24.     border: solid 1px black;
  25.     color: Black;
  26. }
  27.  
  28. a.pagerButtonCurrentPage
  29. {
  30.     border: solid 1px #00a;
  31.     padding: 4px;
  32.     text-decoration: none;
  33.     color: White;
  34.     background-color: #006;
  35.     margin: 0px 2px 0px 2px;
  36. }
  37.  
  38. .pagerButtonDisabled
  39. {
  40.     border: none;
  41.     color: #999;
  42.     padding: 4px;
  43. }

Finalmente, compilamos la aplicación y navegamos a la ruta /Store/Paged donde podemos ver como se obtienen todos los elementos de nuestro modelo estructurados tal y como lo hemos definido en su configuración y como podemos navegar por ellos de forma sencilla.

image

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *