DirectMethods y control GridPanel
Esta parte de la serie sobre Ext.Net va a ser extensa debido a que veremos varios temas: como manejar un evento del lado del servidor con DirectMethods tal como lo he mencionado anteriormente como utilizar el control GridPanel el cual es un grillado que nos permite presentar información, y algunas características especiales de este control como son las barras de herramientas y los renderizadores.
DirectMethods es otra forma de manejar eventos del lado del servidor, para crear un direct method se debe marcar un método con el atributo [DirectMethod], cuando se produce la renderización de la pagina y un método esta marcado con este atributo lo que hace ExtNet es generar código javascript que nos permita invocarlo directamente, por ejemplo:
[DirectMethod] public void Buscar(string nombres, string edad)
se convierte en
Ext.net.DirectMethods.Buscar(nombres,edad)
Así lo podemos invocar directamente desde javascript, en este ejemplo tenemos un control GridPanel que nos presenta una lista de empleados y una sección en donde con criterios de búsqueda: nombres y edad, al presionar el botón buscar se invoca el Direct Method, noten el uso de #{<nombreComponente>}, esto nos permite obtener una referencia al elemento dentro de la pagina por su nombre, aquí lo utilizamos para obtener el valor del campo nombre y edad.
<ext:Button ID="botonBuscar" runat="server" Text="Buscar" Icon="Zoom">
<Listeners>
<Click Fn="buscar" />
</Listeners>
</ext:Button>
var buscar = function () {
var nombres = #{nombreCompletoBusqueda}.getValue();
var edad = #{edadBusqueda}.getValue();
Ext.net.DirectMethods.Buscar(nombres, edad);
}
Cuando presionamos el botón de búsqueda se produce el llamado al método Buscar definido en el servidor, si revisamos los datos de la petición notaran que los valores viajan como extraParams igual que un DirectEvent pero a diferencia de éste no es necesario obtenerlos accediendo a una colección sino que ya son enlazados según los parámetros definidos.
La respuesta es un script en formato JSON que llama al método del store (lo veremos más adelante por ahora piensa en el store como la fuente de datos del GridPanel): callbackRefreshHandler, recordemos que al ser una llamada AJAX se produce un callback cuando se termina de procesar esta petición, la información que contiene la respuesta se divide en dos partes:
- Información de la peticion (serviceResponse, success, etc)
- El contenido de la lista de los empleados, en la propiedad Data
El control llamado store sirve como la fuente de datos para otros controles, por ejemplo: GridPanel, ComboBox, o sea todos aquellos controles orientados a presentar información, este control se asocia directamente al Grid a través de la propiedad Store, posee un Reader definido en este este ejemplo como un JsonReader con una colección de campos,la asignación de IDProperty al campo ID determina la unicidad de los registros en el store, recuerdan que se dijo anteriomente que la respuesta de presionar el botón Buscar estaba en formato JSON, el JsonReader puede interpretar esta respuesta.
<Store>
<ext:Store ID="storeEmpleados" runat="server">
<Reader>
<ext:JsonReader IDProperty="ID">
<Fields>
<ext:RecordField Name="NombreCompleto"></ext:RecordField>
<ext:RecordField Name="Edad"></ext:RecordField>
<ext:RecordField Name="Cargo"></ext:RecordField>
<ext:RecordField Name="FechaContrato"></ext:RecordField>
<ext:RecordField Name="Activo"></ext:RecordField>
</Fields>
</ext:JsonReader>
</Reader>
</ext:Store>
</Store>
GridPanel nos permite tener tres barras una superior (TopBar), otra inferior (BottomBar) y una al pie del control (FooterBar), por defecto tienen determinado un layout tipo Form por esta razón podemos colocar directamente controles tipo TextField, ComboBox y sus valores para FieldLabel se presentaran automáticamente. En este caso se coloco los controles de búsqueda en el TopBar:
<TopBar>
<ext:Toolbar runat="server">
<Items>
<ext:TextField ID="nombreCompletoBusqueda" runat="server" FieldLabel="Nombres" Width="400"></ext:TextField>
<ext:NumberField ID="edadBusqueda" runat="server" FieldLabel="Edad"></ext:NumberField>
<ext:Button ID="botonBuscar" runat="server" Text="Buscar" Icon="Zoom">
<Listeners>
<Click Fn="buscar" />
</Listeners>
</ext:Button>
</Items>
</ext:Toolbar>
</TopBar>
El store corresponde a la parte de datos, ahora veremos como definir la parte de presentación para el GridPanel, esto es determinado por las propiedades ColumnModel y SelectionModel la primera va a definir una colección de columnas, mientras que la segunda establece la forma en que una fila en el Grid puede ser seleccionada.
Así en la colección Columns para ColumnModel tenemos varias columnas con la siguiente estructura
<ext:Column ColumnID="NombreCompleto" DataIndex="NombreCompleto" Header="Nombres"></ext:Column>
ColumnID, en este caso es utilizado para establecer que la columna de Nombres sea principal en el Grid, a través de la propiedad AutoExpandColumn Nombres se expandirá automáticamente hasta completar el ancho del Grid.
DataIndex, es el nombre de un RecordField en el Store, permite enlazar el Store al modelo de columnas y establecer cual es la propiedad que se debe presentar en esta columna, y
Header, que es el texto del encabezado de la columna.
SelectionModel simplemente determina que se puede seleccionar una fila completa y solo una a la vez.
<SelectionModel>
<ext:RowSelectionModel SingleSelect="true" />
</SelectionModel>
Las columnas Edad y Activo tienen un Render o renderizador, estos nos permiten mejorar la experiencia del usuario cuando se presenta la información, por ejemplo, edad es un valor entero, con edadRenderer se crea una cadena con el valor de la columna y la palabra “años”, la columna Activo es un valor booleano, en este caso se utiliza dos iconos para indicar si el empleado si esta activo o no, en lugar de presentar los valores true o false.
var edadRenderer = function (value) {
return value + ' ' + 'años';
}
var activoRenderer = function (value) {
if (value)
return "<img src='drop-yes.gif' alt='Activo' />";
else
return "<img src='drop-no.gif' alt='Inactivo' />";
};
Cada render es una función que recibe implícitamente un parámetro llamado value con el valor de cada uno de los registros, el valor que se devuelve, en este caso una cadena, es lo que se presenta en la celda.
Sin renderizadores tendríamos:
y aplicando los renderizadores, noten como se cambian los valores de las celdas:
Hasta ahora hemos visto la parte visual, del lado del servidor tenemos una clase Empleado como contenedor de los datos de este ejemplo y un repositorio para simular el acceso a una base de datos, algo importante que se ejecuta en el Load de la página es esto:
//X es lo mismo que ExtNet
//if(ExtNet.IsAjaxRequest)
if (!X.IsAjaxRequest){}
X es un alias para la clase ExtNet, contiene varios métodos y propiedades de utilidad, la propiedad IsAjaxRequest que devuelve un valor verdadero si la petición es del tipo AJAX, cuando se carga la pagina por primera vez esta petición no es del tipo AJAX por lo cual llenamos (bind) el store con los datos de todos los empleados.
Hemos cubierto la forma en que se escribe un DirectMethod, un control GridPanel para presentar información de empleados y como utilizar renderizadores para mejorar la experiencia del usuario, en el siguiente post que será el ultimo de esta serie introductoria veremos como paginar un Grid o cualquier otro control que soporte paginación.
Hasta la proxima!
Links útiles:
Eventos del lado del servidor
Continuando con la serie sobre Ext.Net, hoy revisaremos como se implementa un evento del lado del servidor, si te has perdido las dos primeras entregas puedes revisarlas:
Manejadores de Eventos
Un manejador de un evento de Ext.Net tiene la siguiente estructura:
protected void guardar_Click(object sender, DirectEventArgs e)
{
...
}
Los valores enviados desde el formulario están almacenadas en una colección llamada ExtraParams que básicamente es un conjunto de pares (clave, valor), donde clave es un nombre que se especifica para el parámetro y valor es la información contenida en el mismo, es desde esta colección donde podemos acceder a los valores del lado del servidor para poder realizar alguna operación.
Declarando un evento del lado del servidor
Utilizaremos el código de la entrada anterior cuando se revisó el layout básico y validaciones, tenemos un formulario en donde se ingresan los siguientes datos:
- Numero de carné
- Nombres
- Email y
- Edad
Cuando se presiona el botón Aceptar y, habiendo el usuario ingresado los datos obligatorios según las validaciones en el cliente de cada control. se procede al envío de la entrada del usuario hacia el servidor, para ello se declara un evento para el botón Guardar:
<DirectEvents>
<Click OnEvent="guardar_Click" Before="return #{datosEstudiante}.getForm().isValid();" Success="envioExitoso(result);" Failure="envioFallido">
<EventMask ShowMask="true" />
<ExtraParams>
<ext:Parameter Name="numeroCarne" Value="#{numeroCarne}.getValue()" Mode="Raw"></ext:Parameter>
<ext:Parameter Name="nombre" Value="#{nombre}.getValue()" Mode="Raw"></ext:Parameter>
<ext:Parameter Name="correoElectronico" Value="#{correoElectronico}.getValue()" Mode="Raw"></ext:Parameter>
<ext:Parameter Name="edad" Value="#{edad}.getValue()" Mode="Raw"></ext:Parameter>
</ExtraParams>
</Click>
</DirectEvents>
OnEvent, establece el nombre del método que se ejecuta en el servidor.
Before, contiene código en JS que se ejecutar antes del envió de los datos del formulario.
Success, define la función JS que se ejecutara luego que termine el procesamiento del lado del servidor y se devuelva la respuesta al cliente.
Failure, si existió algún error en el procesamiento de los datos la función definida en esta propiedad lo manejará
Y en nuestro código para el evento Click, se puede acceder al valor del numero de carné mediante su clave:
string numeroCarne = (string)e.ExtraParams["numeroCarne"];
StringBuilder sb = new StringBuilder();
sb.AppendLine("Se ha recibido la siguiente informacion:");
sb.AppendFormat("Número de Carné : {0} ", numeroCarne);
sb.AppendFormat("Nombre : {0} ", e.ExtraParams["nombre"]);
sb.AppendFormat("Email : {0} ", e.ExtraParams["correoElectronico"]);
sb.AppendFormat("Edad : {0} ", e.ExtraParams["edad"]);
sb.AppendFormat("a las {0} ", DateTime.Now);
e.ExtraParamsResponse["mensajeConfirmacion"] = sb.ToString();
Luego se estructura una cadena con los valores de cada uno de los parámetros el cual será enviada al cliente dentro de otra colección llamada ExtraParamsResponse que tiene la misma estructura que ExtraParams, con la diferencia de que estos valores se los puede obtener desde el cliente.
var envioExitoso = function (response) {
Ext.Msg.alert('Información', response.extraParamsResponse.mensajeConfirmacion);
};
Hemos cubierto en esta entrada la forma en que Ext.net envía y recibe datos desde el servidor, en la siguiente entrada veremos el tema de DirectEvents DirectMethods que es otra forma de manejar eventos enviar datos al servidor.
Hasta la próxima.
Links útiles:
How the web works: HTTP and CGI explained
Código completo del ejemplo.
Layout Básico y Validaciones con ExtNet
Esta es la segunda parte sobre ExtNet, la primera la pueden encontrar aquí, hoy veremos como crear un layout basico o la disposicion de los controles dentro de la pagina, y como incluir validaciones.
Comenzaremos creando un nuevo proyecto web vacio y escribiendo las configuraciones necesarias para poder incluir los controles de Ext.Net dentro de nuestras páginas, pueden revisar el post anterior o continuar con el siguiente código base.
Lo que queremos lograr es lo siguiente:
En el post anterior ya creamos una ventana (control Window), ahora le añadiremos un conjunto de TextFields y NumberFields y dos clásicos botones, Aceptar y Cancelar.
El esquema básico que se muestra en la figura anterior muestra que tenemos un control tipo Window, dentro de el un FormPanel el cual contiene una colección de controles llamada Items, los botones se los agrupará bajo otra colección llamada Buttons
Dentro de Items colocaremos 2 controles TextField para el nombre del estudiante y su correo electrónico y 2 controles NumberField para el número de carné y su edad.
<ext:NumberField ID="numeroCarne" runat="server" EmptyText="00000" FieldLabel="Número de Carné" AllowBlank="false">
</ext:NumberField>
<ext:TextField ID="nombre" runat="server" EmptyText="Escriba el nombre del estudiante" FieldLabel="Nombres" Width="300" AllowBlank="false">
</ext:TextField>
<ext:TextField ID="correoElectronico" runat="server" EmptyText="Escriba la dirección de correo electrónico"
FieldLabel="Email" Width="300" AllowBlank="false"
Regex="^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$">
</ext:TextField>
<ext:NumberField ID="edad" runat="server" EmptyText="19" FieldLabel="Edad" AllowBlank="false">
</ext:NumberField>
Dentro de Buttons colocaremos 2 botones, Aceptar y Cancelar.
<ext:Button ID="guardar" runat="server" Icon="Disk" Text="Guardar">
<Listeners>
<Click Handler="if(#{datosEstudiante}.getForm().isValid()) Ext.Msg.alert('Confirmación',
'Datos guardados con éxito'); else Ext.Msg.alert('Error', 'Revise los datos del formulario');" />
</Listeners>
</ext:Button>
<ext:Button ID="cancelar" runat="server" Icon="Cancel" Text="Cancelar">
<Listeners>
<Click Handler="#{datosEstudiante}.close()" />
</Listeners>
</ext:Button>
Los controles de Ext.Net poseen la propiedad FieldLabel, esta sirve para establecer el texto de la etiqueta que acompaña al control, solo se visualizará cuando los controles se encuentren dentro de un FormPanel.
Existen varios tipos de validaciones en este caso se ha utilizado las siguientes:
- AllowBlank, estableciendo su valor en falso, indica que se requiere ingresar un valor en el control.
- Regex, el texto ingresado es validado mediante una expresión regular.
También hubiéramos podido establecer una validacion mediente RegEx, para no permitir el ingreso de caracteres no numéricos dentro de los controles número de carné y edad sin embargo al utilizar NumberField ya obtenemos este tipo de validación de la entrada de datos.
En los botones de Aceptar y Cancelar se puede ver que existen declaraciones para el manejo del evento Click, cuando se encuentran dentro de la colección Listeners indican que el manejo de estos eventos se los realizara del lado del cliente, mediante la propiedad Handler vamos a especificar el código Javascript que se ejecutará, en el caso del botón Aceptar se evalúa que el formulario sea valido:
#{datosEstudiante}.getForm().isValid()
para luego presentar un mensaje mediante las funciones de ExtJs, pueden consultar la documentación acerca de MessageBox en http://www.extjs.com/deploy/dev/docs/?class=Ext.MessageBox.
Los controles se marcarán con una línea roja similar a Microsoft Word cuando el control no es valido, además que indicaran un mensaje con el tipo de validación que no esta cumpliendo. En este caso se observa al ubicar el cursor sobre el control nombres se indica que el campo es requerido.
En el evento Click para el botón Cancelar simplemente cerraremos la ventana llamada datosEstudiante.
#{datosEstudiante}.close()
Hemos cubierto la forma de como escribir un layout básico de un formulario y como agregar validaciones para la entrada de datos, en el siguiente post veremos como manejar los eventos del lado del servidor.
Hasta la próxima!.
Links útiles:
- Expresión Regular de Email
- Validacion de formularios
- Código completo del ejemplo
Primeros pasos con Ext.Net y Visual Web Developer Express
En este post voy a hacer una breve introducción al desarrollo de aplicaciones Web con Coolite y Visual Web Developer Express 2010, Coolite es un toolkit de controles para ASP.net que nos permiten utilizar el popular framework de Javascript ExtJS, pueden navegar por los ejemplos aquí.
Actualmente la versión de Coolite es la 0.8.2, sin embargo en su cuenta de Twitter anuncian que la versión 1.0 esta disponible como un preview, si se fijan bien notarán que el anuncio esta marcado bajo el tag #extnet, esto se debe a que en la nueva versión, coolite será renombrado a Ext.Net, luego de descargarlo, vamos a crear un nuevo proyecto Web en VWD, yo lo he llamado Extnet_ParteUno.
Vamos a agregar tres referencias a el proyecto recién creado, los archivos que debemos referenciar son lo siguientes:
-
Ext.Net.dll
-
Ext.Net.Utilities.dll
-
Newtonsoft.Json.dll
Luego en el archivo web.config agregamos dentro de system.web, las siguientes secciones:
<pages> <controls> <add namespace="Ext.Net" assembly="Ext.Net" tagPrefix="ext"/> </controls> </pages>
Esto nos permitirá incluir los controles de Ext.Net dentro de nuestras páginas sin tener que registrar el ensamblado en cada una de ellas.
<httpModules> <add name="DirectRequestModule" type="Ext.Net.DirectRequestModule, Ext.Net" /> </httpModules>
La sección anterior es requerida por extnet, si no la incluimos nuestra aplicación se ejecutará sin embargo aparecerá un mensaje similar al siguiente:
Los controles de Ext.Net requieren que el control ResourceManager se encuentre al inicio de la pagina así:
<ext:ResourceManager ID="rm" runat="server"></ext:ResourceManager>
Voy a agregar un control tipo Window
<ext:Window ID="win" runat="server" Width="800" Height="500" Title="Mi Ventana" > <AutoLoad Url="http://www.coolite.com"> </AutoLoad> </ext:Window>
La ventana tendrá un ancho de 800 px por 500px de alto, como titulo el texto “Mi Ventana” y cargará automáticamente el contenido del sitio de Coolite cuando se muestre la ventana a través de AutoLoad que tiene definida la propiedad Url.
Visualizamos nuestra pagina y deberíamos tener algo similar a:
Pueden descargar el código de este ejemplo aquí.
Este es uno de una serie de posts que hare sobre el desarrollo de aplicaciones web utilizando Ext.Net
Hasta la próxima.
Titulo del Post
- Cuerpo del Post
Actualización: Este post no tiene ningun sentido y solo sirvió para evangelizar a un colega en el tema de los Blogs.
Weird Window in Visual Studio 2008
Every time that I fired up VS2008, a empty, small window appears for a few seconds before VS is completely opened, since I installed SP1 for VS, so yesterday I finally catch the window, this is how its looks like:
I thinks is a orphan window, maybe with SP2 the window is gone.
Visual Studio CodeName Hawaii
After a keynote presented by Paramesh Vaidyanathan, Product Unit Manager of VS Platform & Ecosystem, and Rico Mariani (a.k.a. Bill Murray) Chief Architect of Visual Studio, we have an idea about what is next on Visual Studio CodeName “Hawaii”, they are taking seriously extensibility as well another improvements for VS, here there are a few features:
- WPF-based text editor
- Small, so obviously faster
- More modular, reliable, WPF-based look and feel
- Help developers through Live Search
Using WPF in Visual Studio is an amazing idea, so with WPF Visual Studio will become like ExpressionStudio (just look and feel, I guess), right now on VS2008, the Properties panel on a WPF-Application Project seems to be built with WPF.
My First ASP.NET MVC Application
As an exercise to test the news bits on ASP.NET MVC Framework Preview 3, I have been building a simple application that manages information about books, I called it the BooksStore, it has CRUD operations for authors, publishers, books, catalog of books, some security, authentication and authorization, using LINQ to SQL Classes as the layer to access data and only the use of FormsAuthentication and the MembershipProvider for SQLServer.
Above a screenshot of the catalog it shows a summary of the book that includes the title, authors, publisher, number of pages and price, the title is a link to the “Show” action of the Book Controller for show detailed information of the book.
Also I have a Rss action of the Home controller that renders a rss channel
Now with the new preview 4 of ASP.NET MVC, I have to change the functionality for user access, with this new preview an Account controller is by default on the template, this is a quickstart for us.
Update: Here is the code
AJAX 1.0 and Visual Studio 2008
Visual Studio 2008 allows to built a project targeting a specific framework (2.0, 3.0 and 3.5) this feature is called multi-targeting which is great when we have to maintain an old project, but unfortunately VS2008 doesn’t work by default with web projects that contains AJAX 1.0, the version of the controls(ScriptManager, ScriptManagerProxy, etc) for AJAX Extensions is 3.0, on this state only the AJAX Control Toolkit v3.0 is supported.
In order to add the AJAX Control Toolkit v.1.0 to the Toolbox and can work with projects that support AJAX 1.0 you must perform the following tasks:
- Download the AJAX Extensions for ASP.NET from here and install it.
- Add the controls on System.Web.Extensions.dll to the Toolbox, to do that, right click on AJAXExtensions tab on the Toolbox, choose ‘Choose items’ the Choose Toolbox Items dialog appears, click on Browse and search for the Extensions library usually installed on /ProgramFiles/Microsoft ASP.NET/ASP.NET 2.0 AJAX Extensions, click OK is expected to have to instances of the controls but is not, don’t worry is OK. VS loads the correct version of the extensions according to the configuration of the project.
- Create a new toolbox tab for AJAX Control Toolkit v1.0 and for version 3.0, download it from CodePlex, compile it and add to the toolbox as in step2.
Is everything is right you must see
and for the toolkit something similar
Unfortunately when you create a web project targeting the .net framework 2.0 the web.config file does not contain everything necessary to develop with AJAX, the sample config file on the install directory of the AJAX Extensions 1.0 must be added manually to the project, with projects on framework 3.5 there is not such problem.
Wireless UTPL una prueba a tu paciencia
Es que navegar con la wireless de la UTPL ademas de convertirse en una verdadera tortura tambien puede convertirse en una terapia contra la ira, es como en esa pelicula de Adam Sandler y Jack Nicholson “Locos de Ira” cuando el buen Jack le hace barbaridades al pobre Adam para ver que tan paciente es bueno al final de la pelicula parece que todo va bien y como que queda “curado” pero ya de nuevo con la wireless esta tambien nos juega unas buenas pasadas, que hermoso es ver cuando ya establece una conexión y nos dice “Señal Sobresaliente” WOW! hermoso, pero falso, porque ya cuando ya estamos dispuestos a abrir el google la señal cae dramaticamente a deficiente que p!/¿/!84@*)( ahi mismo te da ganas de arrojar la portatil, capaz que asi alcanza mayor señal
Lo más frustrante es que según la conexion de red es de… 1 Mbps ja ja como si fuera cierto, ya dicen que el infierno esta hecho de buenas intenciones, nuestra tarjeta esta con la intencion de recibir tal cantidad de bits pero la realidad es que no le llega ni siquiera lo que mide la cabecera de un paquete de respuesta, bueno de ahi que si eres paciente talves se conecta y te deja navegar aunque sea para ver que tu profe ha puesto en el EVA que no hay clases, – al menos valio la pena la espera –
Si eres impaciente y quieres terapia nada mas que soportes la conexión con la que se cuenta en la UTPL y estaras curado si no pierdes la razón primero.
NOTA: Generalmente se escribir en inglés pero este post va dedicado a todos los usuarios de la Wi-Fi UTPL