martes, 1 de diciembre de 2009

C# Nuevas Características

Veamos las nuevas características que se han incorporado en cada una de las entregas de este potente lenguaje de programación, comenzando por C# 2.0, C# 3.0 hasta C# 4.0

C# Evolucion, .Net, VS

C# es un lenguaje de programación que ha ido mejorando con el paso del tiempo, agregando nuevas e interesantes características en cada una de las versiones que han ido saliendo progresivamente con cada nueva entrega de Visual Studio, veamos entonces dichas mejoras:

C# 4.0, Lo Nuevo

Con la próxima llegada de Visual Studio 2010, sale la versión C# 4.0, incorporando las siguientes nuevas características:

  1. Parámetros Opcionales.
  2. Tipos Dinámicos (dynamic type).
  3. Covarianza y Contravarianza (Covariance and Contravariance).
Nota: Existen otras muchas nuevas características incorporadas en esta nueva versión (C# 4.0) que iré incorporando a medida que las valla manipulando y comprendiendo ... sean pacientes, jejejeje

C# 3.0, Lo Nuevo

Con la llegada de Visual Studio 2008, sale la versión C# 3.0, incorporando las siguientes nuevas características:

  1. LINQ
  2. Expresiones Lambda (Lambda Expressions).
  3. Tipos Anónimos (Anonymous Types).
  4. Inicializadores de Objetos y Colecciones (Object and Collection Intializers).
  5. Métodos Extensores (Extension Methods).
  6. Expression Trees.
  7. Partial Methods.
  8. Propiedades Auto-Implementadas (Auto-Implemented Properties).

C# 2.0, Lo nuevo

Con la llegada de Visual Studio 2005, sale la versión C# 2.0, incorporando las siguientes nuevas características:

  1. Generics.
  2. Métodos Anónimos (Anonymous Methods).
  3. Iterators.
  4. Partial Types.
  5. Nullable Types.
  6. Delegados (Delegate Inference).
  7. Friend  Assemblies.
  8. Pragma warning.
  9. Captured Variables.

Artículos Relacionados:

viernes, 20 de noviembre de 2009

C#, Inicializadores de Objeto y de Colección

Los inicializadores de objeto permiten asignar valores a los campos o propiedades de un objeto en el momento de la creación sin tener que invocar explícitamente un constructor.

C# 3.0, Nueva Característica

Esta característica fue incorporada a partir de la versión C# 3.0 y sigue el camino de la simplificación de código, al igual que otras características que iré comentando en sucesivos artículos. Pero en fin, veamos un ejemplo que nos deje el concepto del todo claro:

namespace Pruebas
{
    class Program
    {
        static void Main(string[] args)
        {
            // Inicializador de Objeto
            Contacto objContacto =
                new Contacto { IdContacto=1, Nombre="Pedro", Telefono = "601 01 01 01" };
           
            //Inicializador de Colección
            List<Contacto> lstContactos = new List<Contacto>
            {
                new Contacto { IdContacto=1, Nombre="Pedro", Telefono="601 01 01 01" },
                new Contacto { IdContacto=2, Nombre="Maria", Telefono="601 01 01 02" },
                new Contacto { IdContacto=3, Nombre="Juana", Telefono="601 01 01 03" }
            };
        }
    }
 
    public class Contacto
    {
        public int IdContacto {get; set;}
        public string Nombre { get; set; }
        public string Telefono { get; set; }
    }
}

Y así de simple es crearnos un objeto o una colección de objetos e inicializarlos en la misma línea.

Nota: En el ejemplo, hemos usado la clase Contacto y en ella hemos usado otra nueva característica de C# 3.0, se trata de las propiedades auto implementadas. Para obtener más información, consulte Propiedades auto implementadas.

Artículos Relacionados:

lunes, 9 de noviembre de 2009

C# Delegado

Veamos un ejemplo práctico y sencillo del uso de eventos delegados, de forma que nos quede claro su concepto y su uso.

¿Que es un Delegado?

Un delegado (delegate) es un tipo especial de clase cuyos objetos pueden almacenar referencias (punteros, apuntadores) a uno o más métodos, posibilitándonos (desde el objeto) lanzar la ejecución en cadena de todos estos métodos.

Hasta aquí la definición mas sencilla posible, pero igualmente algo complicada de entender, expliquémosla a través de un ejemplo abstracto con la esperanza de que se comprenda algo mejor:

Si tuviéramos una página Page1 y un control de usuario uc1, y quisiéramos desde un método de uc1 llamar a un método de Page1, tendríamos que declarar un delegado en uc1 y desde Page1 almacenar en el delegado el método de la página (uc1.Delegado1 = Page1.Método).

Creo que igual me enrede, en fin veamos un caso práctico y concreto que recientemente tuve, donde usé un delegado (delegate).

Delegado Ejemplo Práctico

Imaginemos la siguiente problemática: Tengo que implementar una búsqueda de vuelos aéreos (ver imagen):

Delegado, Buscador de Vuelo

Para ello crearemos una página que contendrá, entre otras cosas, 2 controles y un método:

  • ucBuscadorCriterios (marcada en rojo): Contiene las condiciones de filtros a establecer para la búsqueda del vuelo.
  • ucBuscadorResultado (marcada en azul): Contendrá los resultados de los vuelos que cumplen las condiciones establecidas.
  • BuscarVuelos(): Método que se encargará de buscar y devolver todos los vuelos que cumplen con unas ciertos criterios de búsqueda. Los criterios son definidos en ucBuscadorCriterios y los resultados los usaremos para mostrarlos en ucBuscadorResultado.

Hasta aquí todo bien, pero si nos fijamos en ucBuscadorCriterios (rojo) dentro tiene el botón btnBuscarVuelos, el cual debe lanzar la búsqueda, o sea, debe llamar al método BuscarVuelos() que está en la página. Nuestro problema sería:

¿Como llamar a Page1.BuscarVuelos() desde Page1.ucBuscadorCriterios?

La respuesta es sencilla, usaremos un delegado (delegate).

Usando Delegado (Delegate)

Lo primero que haremos es declarar el delegado, en nuestro ejemplo debemos abrir el código del control de usuario (ucBuscadorCriterios) y definimos nuestro delegado AereoBuscadorBuscarClick, posteriormente en el evento asociado al clic del botón “Buscar Vuelos” haremos la llamada al delegado AereoBuscadorBuscarClick. Ya lo tenemos casi todo echo solo nos falta asociar el delegado al método que nos interesa Page1.BuscarVuelos().

public partial class UserControlsAereoBuscadorCriterios : UserControl
{
  //Declarar el delegado
  //(puntero a la función que se encuentra en la pagina)
  public delegate void MyDelegadoBuscar();
  public event MyDelegadoBuscar AereoBuscadorBuscarClick;
  protected void Page_Load(object sender, EventArgs e) {}
 
  //Evento asociado al boton AereoBuscadorBuscar y que es un delegado o puntero 
    a la función que se encuentra en la pagina
  protected void AereoBuscadorBuscar_Click(object sender, EventArgs e)
  {
    if (AereoBuscadorBuscarClick == null) return;
   
    AereoBuscadorBuscarClick();
  }
}
Para asociar el delegado que hemos creado (AereoBuscadorBuscarClick) al método de la página (Page1.BuscarVuelos()) tenemos que ir al código de la página y en el evento Page_load hacer la asociación correspondiente:

protected void Page_Load(object sender, EventArgs e)
{
   //Asociar el delegado del control de usuario
   ucBuscadorCriterios.AereoBuscadorBuscarClick += BuscarVuelos;
}

Y todo listo, ya tenemos un ejemplo practico de un delegado (delegate)…

Después de escribir el artículo no se si ha quedado claro la idea de uso de un delegado, espero que se halla entendido.

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: