Handling Events and Delegates : Javier Luna blog

Tuesday, August 24, 2004

Handling Events and Delegates

Una de las cosas mas interesantes que trajo consigo la llegada de ASP.NET, aya por el año 2002, fue la posibilidad de encapsular logica e interfaz de usuario a traves de los ahora muy conocidos Web User Controls.

Esto nos ha permitido reutilizar dichas funcionalidades a lo largo de nuestro projecto web, permitiendo reducir algunas lineas de codigo, haciendo mas sencillo y flexible los posteriores mantenimientos.

Sin embargo, la manera profesional de trabajar con los Web User Controls consiste en definir eventos, a partir de los cuales se envian mensajes hacia la entidad que los contenga, que generalmente son Pages u otros Web User Controls.

La intencion esta en que las paginas ASP.NET, asuman el rol de gestores de los eventos de los diferentes Web User Controls que contengan dentro de el.

Les alcanzo un pequeño ejemplo que podria mostrar lo sencillo que es definir un evento para un Web User Control, haciendo uso de un Delegate que define cierta firma a la que se ha de ajustar el evento que deseamos publicar.


Archivo .ASCX


<%@ Control Language="c#" AutoEventWireup="false" Codebehind="SearchEngine.ascx.cs" Inherits="DemoWebAppCSharp.Event.SearchEngine"%>
<asp:TextBox id="_text" runat="server"></asp:TextBox>
<asp:Button id="_go" runat="server" Text="Go"></asp:Button>

--- End File ---

Este archivo define como se ha de estructurar la interfaz del usuario para este Web User Control en particular.

Algo tan simple como un TextBox y un Button para un sencillo buscador.


Archivo .ASCX.CS



namespace DemoWebAppCSharp.Event
{
using System;
using UserInterface;

/// <summary>
/// Definimos el delegate que define la firma con la que publicaremos el evento
/// </summary>
public delegate void ClickedEventHandler( Object sender, ClickedEventArgs e );

/// <summary>
/// Este Web User Control hereda de un clase que permite encapsular
/// cierta funcionalidad similar para todos los controles de
/// nuestro projecto web
/// </summary>
public class SearchEngine : CustomControl
{
protected System.Web.UI.WebControls.TextBox _text;
protected System.Web.UI.WebControls.Button _go;

/// <summary>
/// Publicamos el evento Clicked del tipo ClickedEventHandler
/// el delegate que habiamos definido lineas arriba
/// </summary>
public event ClickedEventHandler Clicked;

/// <summary>
/// Es requisito sobre-escribir este metodo para todo Web User Control
/// que diga decente :)
/// </summary>
/// <param name="e">Uhmmm... obvio!!!</param>
protected override void OnInit( EventArgs e )
{
base.OnInit( e );

// Enganchamos el metodo SearchEngine_Load al evento Load del control
this.Load += new EventHandler(SearchEngine_Load);

// Enganchamos el metodo Go_Click al evento Click del Button
this._go.Click += new EventHandler( this.Go_Click );
}

private void SearchEngine_Load(object sender, System.EventArgs e)
{
}

/// <summary>
/// Este metodo estara enganchado al evento Click del Button
/// que se muestra en la interfaz del usuario del Web User Control
/// y soltara el evento propio de este control para dicha accion Clicked.
/// </summary>
/// <param name="sender">Una instancia de quien ocasiona el evento</param>
/// <param name="e">Informacion del evento</param>
private void Go_Click(
Object sender,
EventArgs e )
{
// Lanzamos el evento Clicked. Alguien lo gestionara y sino no hay problema
if( this.Clicked != null )
this.Clicked( this, new ClickedEventArgs( this._text.Text ) );
}
}

/// <summary>
/// Esta clase encapsula cierta informacion particular para el evento Clicked
/// del Web User Control que estamos implementando SearchEngine.
/// Lo unico que enviara es el texto que fue ingresado en el TextBox del
/// control para que se realize la accion esperada del usuario.
/// </summary>
public class ClickedEventArgs : EventArgs
{
private String _text;

public ClickedEventArgs( String Text )
{
this._text = Text;
}

public String Text
{
get { return this._text; }
set { this._text = value; }
}
}
}

--- End File ---

Aqui implementamos la manera en como nuestro Web User Control ha de interactuar con el usuario. En funcion a las opciones que permitamos, realizaremos ciertas acciones a traves de Eventos. En este caso particular, al hacer 'click' sobre el Button lanzaremos el evento Clicked propio de este Web User Control.

Para ello tenemos que engancharnos al evento Click del Button y dentro de su implementacion disparar nuestro propio evento, Clicked.

Debido a que tenemos la intencion de enviar cierta informacion a traves del evento. La manera de llevarlo a cabo es usando el definiendo una clases que herede de EventArgs. En nuestro caso particular ClickedEventArgs. El cual solo cuenta con una propiedad llamada Text, donde colocaremos el dato que haya ingresado el usuario sobre el TextBox del Web User Control.

El evento que publicaremos debe ajustarse al Delegate que hemos definido, ClickedEventHandler. Este delegate se ajusta a cierta firma, propia para este evento.

No hubiera sido necesario definir este Delegate si no hubieramos visto conveniente una firma particular para el evento o enviar informacion a traves de el.

En ese caso, hubiera sido suficiente definir el evento Clicked del tipo EventHandler, el delegate por default. De ese modo, ya no seria necesario enviar informacion adicional como parte del evento. Entonces tendrias que usar EventArgs.Empty en el momento de lanzar el evento Clicked.



Archivo .ASPX



<%@ Register TagPrefix="Custom" TagName="SearchEngine" Src="SearchEngine.ascx" %>
<%@ Page language="c#" Codebehind="Holder.aspx.cs" AutoEventWireup="false" Inherits="DemoWebAppCSharp.Event.Holder" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>Holder</title>
</HEAD>
<body>
<form id="Form1" method="post" runat="server">
<table>
<tr>
<td>
<Custom:SearchEngine id="_engine" runat="server"></Custom:SearchEngine></td>
</tr>
<tr>
<td>
<asp:TextBox id="_show" runat="server"></asp:TextBox>
</td>
</tr>
</table>
</form>
</body>
</HTML>

--- End File ---

Este archivo contiene el Web User Control y un TextBox.

La intencion con propositos de testeo, es la de pintar el texto ingresado por el TextBox del Web User Control sobre el TextBox de la Page.


Archivo .ASPX.CS



namespace DemoWebAppCSharp.Event
{
using System;
using UserInterface;

/// <summary>
/// Esta es la pagina que contendra el Web User Control que hemos implementado
/// Por cierto, hereda de una pagina que define cierta funcionalidad similar
/// para todas las paginas de nuestro proyecto web.
/// </summary>
public class Holder : CustomPage
{
protected System.Web.UI.WebControls.TextBox _show;
protected SearchEngine _engine;

/// <summary>
/// Del mismo modo, que para el Web User Control es requisito para
/// toda Page que se diga decente.
/// </summary>
/// <param name="e"></param>
protected override void OnInit( EventArgs e )
{
base.OnInit( e );

// Enganchamos el metodo Holder_Load al evento Load de la page
this.Load += new EventHandler(Holder_Load);

// Enganchamos el metodo Engine_Clicked al evento Clicked de Web User Control
this._engine.Clicked += new ClickedEventHandler( this.Engine_Clicked );
}

private void Holder_Load(object sender, System.EventArgs e)
{
}

/// <summary>
/// Este es el metodo que se enganchara al evento Clicked del Web User Control
/// y que dentro de su implementacion realizara la tarea que creemos
/// conveniente. Pero dicha accion estara dentro de la jurisdiccion de la Page.
/// </summary>
/// <param name="sender">La instancia de quien genera el evento</param>
/// <param name="e">Informacion propia de este evento</param>
private void Engine_Clicked(
Object sender,
ClickedEventArgs e )
{
// Algo tan sencillo como pintar el texto ingresado por el control sobre otro TextBox
this._show.Text = e.Text;
}
}
}

--- End File ---

Para llevar a cabo dicho testeo, tenemos que subscribirmos al evento Clicked del Web User Control. De esa manera, coger la informacion que trae consigo el evento para poder realizar una accion. En este caso, ClickedEventArgs nos brinda el dato que el usuario hubiera ingresado sobre el TextBox del Web User Control. El cual nosotros cogeremos para poder colocarlo sobre el TextBox de la Page.

No comments: