Controles Windows en Web(c#) Fecha: 11/Sep/2003 (14/Sep/2003) |
. |
En esta segunda parte intentaremos completar más cosas sobre la técnica de embeber controles Windows en Web. En mi anterior colaboración he explicado como crear un control simple y como introducirlo en el iexplorer para ser ejecutado por el cliente de esa web. En esta colaboración trataré de explicaros como inicializar nuestros controles mediante tag de Html, lo que facilitará la reusabilidad de los controles, puesto que podemos adaptar el controles a cada web sin necesidad de volver a cambiar código y volver a compilarlo. Aprenderemos también, y esto me parece lo más interesante, como generar eventos y que estos sean capturados desde la web mediante scripts (jscript o vbscript) lo que nos facilitará muchísimo la sincronización del control con otras acciones propias de la web que necesitemos realizar.
Primeramente creamos un control web, tal y como explicamos en la anterior colaboración. una vez creado y asignado el nombre que deseemos a nuestro control creamos un atributo nuevo que en mi caso le llamaré ParamPasado y que será de tipo string.
private string pasado; public string ParamPasado { get{ return pasado;} set{this.pasado = value ;} }Con esto ya hemos creado el atributo que vamos a inicializar, ahora veremos como inicializarlo desde un tag de Html. Como sab�is us�bamos object para incluir el control en la web, pues bien entre el inicio y el cierre incluimos lo siguiente
<param name="ParamPasado" value="esto es el parametro pasado en el tag param">
Bien! con esto ya podemos inicializar los controles y que tal y como comente antes nos facilitar� mucho la reutilizaci�n de los controles en diversas webs. Vamos entonces con el plato fuerte, tomarlo con calma eh!!. Nuestra tarea es conseguir que un evento soltado por nuestro control sea capturado por un script de una p�gina web, Buff! por lo menos eso fue lo que dije yo cuando me vi en la situaci�n de tener que crear un control que necesitaba sincronizarse con una p�gina en Html. Bueno despu�s de leer bastante de la SDK de .NET Framework y diversas consultas, entre ellas al Guille y a Erich B�hler (www.vblibros.com), la soluci�n que he encontrado es exponer el control windows como un objeto COM declarando los eventos y miembros p�blicos del control y definiendo la interface adecuada. Para ello necesitaba, como sabr�is los que teng�is algo de idea de COM es un identificador �nico para eso objeto, esto no es problema puesto que Visual Studio nos proporciona esta utilidad, para crear uno pod�is ejecutar guidgen en el s�mbolo del sistema que biene con el Visual Studio, o directamente en el Visual Studio dirigi�ndonos a Herramientas -> Crear Guid, nos saldr� algo como esto:
Seleccionamos la opción 4 y hacemos click en Copy, ¿ fácil no ? Bueno pues con esto hemos creado un identificador "único" en en mundo que servirá para identificar a nuestro objeto. Bueno ya tememos nuestro guid, guardarlo en un documento de texto para usarlo más tarde ok?
Para crear un evento primero necesitamos crear un delegado y despu�s asociar al evento este delegado, que básicamente es un puntero a una función. El código para crear el evento es el siguiente.
public delegate void TerminarHandler(); public event TerminarHandler Terminado;Ahora que hemos visto como crear el Guid del control y como crear un evento estamos en disposici�n de crear definitivamente el control. Escribimos el c�digo y despu�s pasamos a comentarlo.
using System; using System.Collections; using System.ComponentModel; using System.Drawing; using System.Data; using System.Windows.Forms; using System.Runtime.InteropServices; namespace controltest2 { ////// Descripci�n breve de UserControl1. /// [ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(typeof(IQCDCOMEvents))] public class micontrol2 : System.Windows.Forms.UserControl,IQCDCOMIncoming // esto no aparece en el c�digo pero lo pongo para explicar alguna cosa { private System.Windows.Forms.Button bt1; ////// Variable del dise�ador requerida. /// private System.ComponentModel.Container components = null; public delegate void FinHandler(); public event FinHandler OnFin; private string pasado; public string ParamPasado { get{return this.pasado;} set{this.pasado = value;} } public micontrol2() { // Llamada requerida por el Dise�ador de formularios Windows.Forms. InitializeComponent(); // TODO: agregar cualquier inicializaci�n despu�s de llamar a InitForm } ////// Limpiar los recursos que se est�n utilizando. /// protected override void Dispose( bool disposing ) { if( disposing ) { if( components != null ) components.Dispose(); } base.Dispose( disposing ); } #region Component Designer generated code ////// M�todo necesario para admitir el Dise�ador, no se puede modificar /// el contenido del m�todo con el editor de c�digo. /// private void InitializeComponent() { this.bt1 = new System.Windows.Forms.Button(); this.SuspendLayout(); // // bt1 // this.bt1.Location = new System.Drawing.Point(24, 64); this.bt1.Name = "bt1"; this.bt1.TabIndex = 0; this.bt1.Text = "Aceptar"; this.bt1.Click += new System.EventHandler(this.bt1_Click); // // micontrol2 // this.Controls.AddRange(new System.Windows.Forms.Control[] { this.bt1}); this.Name = "micontrol2"; this.ResumeLayout(false); } #endregion private void bt1_Click(object sender, System.EventArgs e) { bt1.BackColor = System.Drawing.Color.Blue; bt1.Text = ParamPasado.ToString(); //Lanzamos el evento, si es lanzado y no se implementa saltar� una excepcion por lo que para algo serio se deber�a cachear OnFin(); } } #region exponemos los eventos [Guid("2BA61129-37D3-4b84-BA47-020F7493A5A3")] [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] public interface IQCDCOMEvents { [DispId(0x60020000)] void OnFin(); } // //Necesitamos declarar aqui lo publico de la clase, por lo de el rollo de la especificacion de COM public interface IQCDCOMIncoming { string ParamPasado{get;set;} } #endregion }Explicación del código.
Como se puede ver se necesita incluir el espacio de nombres System.Runtime.InteropServices para exponer el control como COM. Usamos ClassInterface para especificar que deseamos exponer el control como COM, se le pasa como parámetro la interface IQCDCOMEvents para decirle cuales son los eventos que pueden ser tratados en la Web. La clase del control se puede derivar de IQCDCOMIncoming para que así mismo podamos decirle que atributos o métodos pueden ser llamados desde jscript o vbscritp, esto no lo he hecho en el control pero bueno aquí lo explico. Una vez creado esto fuera del cierre de la clase se crear las interface que he mencionado y aquí es donde se usa lo que habíamos aprendido del GUID, para la interface IQCDCOMEvents, si se crean varios eventos a tratar deben tener un identificador distinto dentro del control, en este caso solo necesitamos que sean distintos dentro del objeto yo uso 0x60020000 y para los siguientes eventos pues 0x600200001 etc ...
Fijaros como se declara ParamPasado en IQCDCOMIncoming, ¡ Cuidado los atributos como ParamPasado o métodos que deseemos que sean tratados deben declararse como public dentro de la clases, esto es importante.!!
Bueno espero que esto os sirva de utilidad, y que aprovech�is toda la potencia de .NET. Se que a muchos no os parecer� muy claro lo de exponer el objeto como COM y tampoco tengo mucho para rebatir aunque bueno esto funciona o sea que.......
C�digo de ejemplo (unaiWebControl2parte.zip - 21.2 KB)
Ejemplo para incluir en el "localhost": unaiWebControl2parteWwwroot.zip 3.42 KB