lunes, 19 de octubre de 2009

jqGrid con ASP.NET y AJAX

jqGrid, Grid jQuery, jqGrid en ASPNET

jqGrid es una excelente grilla (grid) para mostrar y manipular datos en forma tabular. A mi juicio mucho más elegante y potente que el GridView de ASP.NET.

En este articulo veremos el código de ejemplo de implementación de un jqGrid con ASP.NET. Además de poder ver una demo en acción del Grid para jQuery, podremos descargarnos la solución completa.

Pero comentemos el problema que nos planteamos resolver.

jqGrid - ASP.NET, Ejemplo

Asumamos que tenemos una base de datos con una tabla Person, que contiene los datos de determinadas personas y queremos mostrar dicha información en una pagina web, tal como se muestra en la figura:jqGrid, jqGrid Demo, jqGrid ASP.NET, Grid jQuery, jqGrid en ASPNET

Para ello decidimos usar el componente jqGrid de jQuery, entre otras cosas porque:

  • Es una grilla (grid) vistosa y elegante.
  • Nos proporciona gran funcionalidad en el manejo y manipulación de los datos.
  • Al usar AJAX y JSON hace más amigable la navegación del cliente.
  • Nos permite paginado, ordenación, selección múltiple, contraer todo el grid, etc.

Pero como de costumbre vallamos al código que debemos implementar, y analicémoslo paso a paso.

Nota: Como el código es bastante amplio, al final hemos dejado un enlace donde podrás descargarte la solución demo (de ejemplo) competa, así como un BackUP de la base de datos SQL.

jqGrid – ASP.NET - HTML

1. Veamos el código del fichero jqGridEjemplo.aspx y después lo comentaremos:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="JqGridEjemplo.aspx.cs" Inherits="JqGridEjemplo" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head runat="server">
    <title>JQGrid con JSON Ejemplo Básico</title>
    <link type="text/css" rel="stylesheet"
          href="css/cupertino/jquery-ui- 1.7.2.custom.css" />
    <link type="text/css" rel="stylesheet"
          href="css/ui.jqgrid.css" />
   
    <script type="text/javascript" src="js/jquery-1.3.2.min.js" ></script>
    <script type="text/javascript"
            src="js/jquery-ui-1.7.2.custom.min.js" ></script> 
    <script type="text/javascript" src="js/grid.locale-sp.js" ></script>   
    <script type="text/javascript" src="js/jquery.jqGrid.min.js" ></script>
    <script type="text/javascript" src="js/grid.base.js" ></script>
    <script type="text/javascript" src="js/grid.common.js" ></script>
    <script type="text/javascript" src="js/grid.formedit.js" ></script>
    <script type="text/javascript" src="js/jquery.fmatter.js" ></script>
    <script type="text/javascript" src="js/json2.js" ></script>
   
    <script type = "text/javascript"> 
      jQuery(document).ready(function()
      {
        $("#grid").jqGrid(
        {
            datatype: function()
            {
              $.ajax(
                {
                  url: "jqGridEjemplo.aspx/GetPersons", //PageMethod
                   
                    data:
                     "{'pPageSize':'" + $('#grid').getGridParam("rowNum") +
                     "','pCurrentPage':'" + $('#grid').getGridParam("page") +
                     "','pSortColumn':'" + $('#grid').getGridParam("sortname") +
                     "','pSortOrder':'" + $('#grid').getGridParam("sortorder")
                       + "'}", //Parametros de entrada del PageMethod
                   
                    dataType: "json",
                    type: "post",
                    contentType: "application/json; charset=utf-8",
                    complete: function(jsondata, stat)
                    {
                      if (stat == "success")
                        jQuery("#grid")[0].addJSONData(JSON.parse
                              (jsondata.responseText).d);
                      else
                        alert(JSON.parse(jsondata.responseText).Message);
                    }
                });
            },
            jsonReader : //jsonReader –> JQGridJSonResponse data.
            {
                root: "Items",
                page: "CurrentPage",
                total: "PageCount",
                records: "RecordCount",
                repeatitems: true,
                cell: "Row",
                id: "ID"
            },
            colModel: //Columns
            [
                { index: 'Name', width: 200, align: 'Left',
                  label: 'Nombre' },               
                { index: 'LastName', width: 300, align: 'Left',
                  label: 'Apellidos' },
                { index: 'BirthDate', width: 200, align: 'Center',
                  label: 'Fecha Nacimiento' },
                { index: 'Weight', width: 100, align: 'center',
                  label: 'Peso (Kg)' }
            ],
            pager: "#pager", //Pager.
            loadtext: 'Cargando datos...',
            recordtext: "{0} - {1} de {2} elementos",
            emptyrecords: 'No hay resultados',
            pgtext : 'Pág: {0} de {1}', //Paging input control text format.
            rowNum: "10", // PageSize.
            rowList: [10,20,30], //Variable PageSize DropDownList.
            viewrecords: true, //Show the RecordCount in the pager.
            multiselect: true,
            sortname: "Name", //Default SortColumn
            sortorder: "asc", //Default SortOrder.
            width: "760",
            height: "230",
            caption: "Personas"
        }).navGrid("#pager", {edit:false, add:false, search:false,
                              del:false});      
      }); 
    </script>
   
  </head>
  <body>
    <table id="grid"></table>
    <div id="pager"></div>
  </body>
</html>

En el código anterior, hemos definido el jqGrid, o sea, la tabla de datos de personas.

Dentro de la etiqueta body encontraras solo 2 elementos; table (grid) que será donde se pintaran los valores de las personas en formato tabular, y la etiqueta div (pager) que será donde aparecerán los datos que encontramos en el pie de la tabla (actualizar, paginación e información general).

En el head encontramos 2 hojas de estilos y los javascript necesarios para dotar al grid de la funcionalidad necesaria, pero por esto no nos preocuparemos ahora, más adelante les indicaremos donde nos podemos descargar estos ficheros.

En el head encontramos también la función $("#grid").jqGrid() que es la encargada de configurar todo el comportamiento del jqGrid o grilla. Dentro de esta función definiremos las propiedades, métodos y eventos, en nuestro ejemplo hemos definido algunas funciones que son muy intuitivas y generales. Una  de estas propiedades es datatype, a esta le asociaremos la función de la llamada AJAX que nos devolverá la lista de personas a mostrar en formato JSON.

jqGrid – ASP.NET – C#

La carga de los datos a mostrar, se hace de forma parcial vía AJAX, o sea, cada vez que el usuario pagine, ordene o haga cualquier acción que necesite recargar nuevos datos, se llamará a la función $.ajax({ url: "jqGridEjemplo.aspx/GetPersons", data:… en nuestro caso es un WebMethod, también podría ser un WS o WCF, pero veamos ahora el code-behind en C# que invocaremos vía AJAX. Este método recibe 4 parámetros que le pasaremos en el parámetro data que vimos anteriormente (pPageSize, pCurrentPage, pSortColumn, pSortOrder). Veamos el código en C#:

public partial class JqGridEjemplo : Page
{
    protected void Page_Load(object sender, EventArgs e) {}
 
    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public static JQGridJsonResponse GetPersons(int pPageSize,
                   int pCurrentPage, string pSortColumn, string pSortOrder)
    {
        return GetPersonasJSon(pPageSize, pCurrentPage, pSortColumn,
                               pSortOrder);
    }
 
 
    internal static JQGridJsonResponse GetPersonasJSon(int pPageSize,
                    int pPageNumber, string pSortColumn, string pSortOrder)
    {
        SqlConnection sqlCon = new SqlConnection ConfigurationManager.
                  ConnectionStrings["DataConnection"].ConnectionString);
        SqlCommand command = new SqlCommand("GetPersons", sqlCon);
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.Add("PageSize", SqlDbType.Int).Value = pPageSize;
        command.Parameters.Add("CurrentPage", SqlDbType.Int).Value =
                  pPageNumber;
        command.Parameters.Add("SortColumn", SqlDbType.VarChar, 20).Value =
                  pSortColumn;
        command.Parameters.Add("SortOrder", SqlDbType.VarChar, 4).Value =
                  pSortOrder;
 
        DataSet dataSet = new DataSet();
        SqlDataAdapter dataAdapter = new SqlDataAdapter(command);
        dataAdapter.Fill(dataSet);
 
        var persons = new List<Person>();
        foreach (DataRow row in dataSet.Tables[1].Rows)
        {
            Person person = new Person
            {
                ID = Convert.ToInt32(row["ID"]),
                Name = row["Name"].ToString(),
                LastName = row["LastName"].ToString(),
                BirthDate = Convert.ToDateTime(row["BirthDate"]),
                Weight = Convert.ToSingle(row["Weight"])
            };
            persons.Add(person);
        }
 
        return new JQGridJsonResponse(Convert.ToInt32(dataSet.Tables[0].
                     Rows[0]["PageCount"]), Convert.ToInt32(dataSet.
                     Tables[0].Rows[0]["CurrentPage"]),
                     Convert.ToInt32(dataSet.Tables[0].Rows[0]["RecordCount"]),
                     persons);
    }
}

En el código anterior, vemos la definición del WebMethod GetPersons, el cual devolverá solo los registros o personas que se mostraran en el jqGrid, estos datos serán devueltos en formato JSON. Si analizamos el código en profundidad, veremos que se hace una llamada a un procedimiento almacenado SQL Server, que devolverá 2 conjuntos de datos, uno con el subconjunto de personas a mostrar y otro con el total de registros de la tabla personas. Pero veamos el procedimiento almacenado:

ALTER procedure [dbo].[GetPersons]
 
@PageSize int ,
@CurrentPage int ,
@SortColumn varchar(20),
@SortOrder varchar(4)
 
as
 
declare @RecordCount int
declare @PageCount int
declare @PageIndex int
 
Select @RecordCount = count(ID)
from Person
 
set @PageCount = Ceiling(cast (@RecordCount as float) / cast (@PageSize as float))
 
if (@CurrentPage > @PageCount) set @CurrentPage = @PageCount
 
set @PageIndex = @CurrentPage - 1
 
Select RecordCount = @RecordCount, PageCount = @PageCount, CurrentPage = @CurrentPage
 
declare @Query varchar(300)
 
set @Query =
      'Select ID, Name, LastName, BirthDate, Weight,
       RowNumber = ROW_NUMBER() OVER (ORDER BY ' + @SortColumn + ' ' + @SortOrder + ')
       from Person'
 
set @Query =
      'Select ID, Name, LastName, BirthDate, Weight
       from (' + @Query + ' )as result
       where RowNumber BETWEEN ' + cast(@PageSize * @PageIndex + 1 as varchar(10)) + '
                    AND ' + cast(@PageSize * (@PageIndex + 1) as varchar(10))
 
Exec (@Query)

Y con esto y poco más ya  tenemos implementado nuestro grid de jQuery (jqGrid), una excelente rejilla de datos que no te dejará indiferente.

Descargar la solución completa de ejemplo de jqGrid en ASP.NET C#.

Para ver otros ejemplos de jqGrid en la página oficial, pinche aquí.

Nota: Existe ya desarrollado un componente jqGrid especial para ASP.NET con un modelo de programación API muy similar al usado en nuestros desarrollos ASP.NET cotidianos, pero la licencia de este otro componente está entre $300.00 y $450.00 (demo), por lo que mi consejo es que usen el jqGrid estándar que hemos explicado aquí que es GRAAAATISSSSSS.

Artículos relacionados:

sábado, 17 de octubre de 2009

Google Maps para ASP.NET

GoogleMaps

Google Map (GMaps) es un control de usuario ASP.NET para con escasas líneas poder agregar mapas de Google o Google Map a nuestras aplicaciones WEB.

Con este control podremos desarrollar aplicaciones WEB en ASP.NET con toda la potencia de la API oficial de GoogleMaps.

Ver demo.

Pero veamos un ejemplo paso a paso. Lo primero será descargarnos el fichero GMaps.dll desde el siguiente enlace.

Una vez descargado y copiado en la carpeta bin de nuestro proyecto, pasaremos a crear nuestra página web a la que le adicionaremos el mapa o Google Map. El código ASPX sería el siguiente:

Google Maps, ASP.NET ASPX

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="GoogleMaps.aspx.cs" Inherits="GoogleMaps" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<%@ Register Assembly="GMaps" Namespace="Subgurim.Controles" TagPrefix="cc" %>

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title></title>

</head>

<body>

    <form id="form1" runat="server">

    <div style="width:660px; height:560px;">

      <cc:GMap ID="GMap1" runat="server" />

    </div>

    </form>

</body>

</html>

Lo próximo que debemos hacer es conseguir una Key, pues lo exige Google para poder utilizar su API. La podemos conseguir desde aquí. Debemos tener en cuenta que esta clave depende del dominio donde vayamos a utilizarla, por lo que por cada Web donde utilicemos GoogleMaps.Subgurim.NET debemos obtener la Key apropiada.

Google Maps, ASP.NET web.config

El modo más sencillo donde ubicar la clave es en vuestro web.config:
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
    ...
    <appSettings>
        <add key="googlemaps.subgurim.net" value="tuClave_yourKey" />
    </appSettings>
     ...
</configuration>

De este modo, el control ya se encargará de hacer el resto.

Llegados a este punto ya tenemos un Mapa de Google en nuestra WEB ASP.NET, de echo, si ejecutamos el proyecto, veremos que ya contamos con un mapa en nuestras pagina ASP.NET. Pero para sacarle el verdadero partido a este mapa debemos configurar algunas cosillas mas, por ejemplo hagamos que se muestre una dirección especifica, por ejemplo la ubicación de nuestra empresa o vivienda y mostremos además un globo con información relacionada a ese punto. En la siguiente imagen se ve el resultado del Google Map que deseamos crear:

GoogleMaps esASP.NETEste control nos proporciona todo el poder de la API oficial de GoogleMaps sin necesidad de una sola línea de código javascript. Así que veamos como dotar a nuestro mapa de alguna de las características de la API desde codebihind, para ello usaremos C#.

Google Maps, ASP.NET C#

using System;
using System.Web.UI;
using Subgurim.Controles;
 
public partial class GoogleMaps : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            GLatLng ubicacion = new GLatLng(40.381090863719436, -3.6222052574157715);
         GMap1.setCenter(ubicacion, 15);
 
            //Establecemos alto y ancho en px
            GMap1.Height = 560;
            GMap1.Width = 660;
 
            //Adiciona el control de la parte izq superior (moverse, ampliar y reducir)
            GMap1.addControl(new GControl(GControl.preBuilt.LargeMapControl));
 
            //GControl.preBuilt.MapTypeControl: permite elegir un tipo de mapa y otro.
            GMap1.addControl(new GControl(GControl.preBuilt.MapTypeControl));
           
            //Con esto podemos definir el icono que se mostrara en la ubicacion
            //#region Crear Icono
            //GIcon iconPropio = new GIcon();
            //iconPropio.image = "../images/iconBuilding.png";
            //iconPropio.shadow = "../images/iconBuildingS.png";
            //iconPropio.iconSize = new GSize(32, 32);
            //iconPropio.shadowSize = new GSize(29, 16);
            //iconPropio.iconAnchor = new GPoint(10, 18);
            //iconPropio.infoWindowAnchor = new GPoint(10, 9);
            //#endregion
 
            //Pone la marca de gota de agua con el nombre de la ubicacion
            GMarker marker = new GMarker(ubicacion);
            string strMarker = "<div style='width: 250px; height: 185px'><b>" +
                "<span style='color:#ff7e00'>es</span>ASP.NET</b><br>" +
                " C/ Jesus del Pino, 10 <br /> 28031 Madrid, España <br />" +
                "Tel: +34 902 00 00 00 <br />Fax: +34 91 000 00 00<br />" +
                "Web: <a href='http://www.esASP.net/' class='txtBKM' >www.esASP.net</a>" +
                "<br />Email: <a href='mailto:derbis.corrales@gmail.com' class='txtBKM'>" +
                "derbis.corrales@gmail.com</a><br><br></div>";
            GInfoWindow window = new GInfoWindow(marker, strMarker, true);
            GMap1.addInfoWindow(window);
 
            GMap1.enableHookMouseWheelToZoom = true;
 
            //Tipo de mapa a mostrar
            GMap1.mapType = GMapType.GTypes.Normal;
 
            //Moverse con el cursor del teclado
            GMap1.enableGKeyboardHandler = true;
        }
    }
}

En el código C# hemos comentado alguna de las características que podemos implementar con este interesantísimo control, y esos comentarios hablan por si solos, por lo que no veo la necesidad de explicarlos mas, pero este control tiene muchas mas funcionalidades que podrás aprenderlas en la web oficial.

El único pero de este control es que la variante gratuita es totalmente funcional, pero no debemos usarla en proyectos comerciales, pues la licencia comercial tiene un coste de 10 €, pero a mi juicio no es nada en comparación con la productividad que logramos al usarlo.

Espero les sea útil este control…