23.9.06

Delegados, Eventos y Métodos anónimos

Introducción: Implementando una interfaz gráfica con windows forms, teniendo un MDI principal y un par de formularios hijos, vi la necesidad que en un momento dado, un formulario hijo realice algo que el padre tiene que interceptar, y tomar cartas en el asunto. En este caso necesitaba setear la propiedad Text del MDI, a partir de alguna acción de un formulario hijo; algo sencillo.

En C# y sin la posibilidad de usar algo análogo al namespace My, que posee la gente de VB.Net, tuve que recurrir a un Eventos y Delegados,...y ya que estamos...Métodos anónimos.

En VB.Net, estando en formulario hijo con el namespace my seria algo bastante tonto:

My.Forms.MDIMain.Text = nombredeltitulo

En C# me las arregle con un mecanismo que permita que el padre (MDI principal) se quede a la "escucha" de un evento, y así iniciar acciones, pero con información que le provee el hijo. Es decir:

  • Los metodos a ejecutar: son del MDI principal
  • Y la información necesaria -los parametros- : provienen del form hijo.

Ahora bien, como se podrían implementar estos tres conceptos juntos para resolver esto ?

Ahora pasemos a un ejemplo donde se vé una interacción entre los objetos:

using System;

// Declaracion del delegado

public delegate void EventHandler(string str);

public class Program
{
public static void Main()
{
TestHandler tb
= new TestHandler();

//Tres maneras de hacer lo mismo

//1- asignacion comun

tb.Evento += new EventHandler(MetodoStringToUpper);

//2- asignacion por inferencia de tipos
tb.Evento += MetodoStringToLower;

//3- asignacion con metodo anonimo

tb.Evento += delegate(string str)
{
string otrostring =
String.Format(
"Metodo Anonimo: {0}",str);
Console.WriteLine(otrostring);
};
tb.Disparar();

Console.ReadLine();
}

public static void MetodoStringToUpper(string str)
{
Console.WriteLine(str.ToUpper());
}

public static void MetodoStringToLower(string str)
{
Console.WriteLine(str.ToLower());
}
}


class TestHandler
{
//Evento de tipo EventHandler
public event EventHandler Evento;


public void Disparar()
{
string mystring = "Dario.Net";

//Disparo el evento, con un string de parámetro

Evento(mystring);
}
}

Primeramente declararemos un delegado: EventHandler, que podrá apuntar a metodos que contengan como argumentos el tipo string y que no retornen valores (void).

Luego en la clase TestHandler se declara un evento: Evento, del tipo EventHandler (nuestro delegado).

Y la funcion: Disparar(); se encargará de disparar el evento con un string como argumento: mystring="Dario.Net".

Vayamos al Main().

Instanciamos un objeto del tipo TestHandler, con el operador += y vamos agregando al evento, todos los métodos que queremos que se ejecuten, uno tras otro.

Luego invocamos a Disparar(). y se invocan, en este orden los tres métodos: MetodoStringToUpper,MetodoStringToLower y el querido metodo anónimo.

Cosas a notar:

El que dispara el evento es el TestHandler, y le pasa un parámetro: mystring.

Los métodos están en el Main, pero esos métodos se ejecutarán por el hijo...cosa loca no ?

El método anonimo: es como si fuera un metodo más, pero definido en el momento de su uso, e inline (buenísimo!)

Bien, ahora que vimos el ejemplo (y espero que lo hayan entendido), imaginemos algo: hagamos de cuenta que Program es el Main, y TestHandler es el Form1. Y podemos solucionar facilmente el problema que plantee al comienzo...y muchos más!

Para profundizar les recomiendo este artículo.

Saludos y dejen comentarios.

5 Comments:

  • Muy raro lo tuyo. Se supone que los forms cuando los haces MDI tenes que ponerle la propiedad MdiParent = form hijo. Tomano ventaja de eso yo de cabeza me mando a MdiParent.Text = "cualkiera";

    en el peor de los casos haces cast de MdiParent al tipo que es, si es que le agregaste metodos y queres llamarlos. Me perdi de algo? :$

    By Anonymous Anonymous, at 6:48 PM  

  • Buen tip Guille. La verdad que con este approach queda solucionado facilmente el problema con los MDI y el .Text, y usando el casting se puede usar todo del Mdi que esté usando.
    Pero para enfoques más complejos se queda corto. Podría usarse tambien para el caso de que varios formularios estén esperando por un evento, por ejemplo si se llama a algún formulario que realiza una busqueda, y el resultado afecta a varios forms que están activos.
    Tiene más un gustivo a observer :)
    Si hay algo que me gusta de .Net es la manera de implementar facilmente los patrones conocidos.

    Para conocer sobre Observer:
    Patron Observer

    By Blogger Dario Quintana, at 5:05 PM  

  • Claro, segun lo que tengo entendido delegates / events y las cosas esas (otra vez) no es invento de Microsoft. Delegates en .net es mas bien una implementacion de observer, yo no diría que observer es facil de implementar en .net sino facil de usar.

    Este es solo uno de los ejemplos de distintos patrones que estan integrados en el .net. Tambien podes citar Composite Design pattern cuando creas un componente (clase Component)

    By Anonymous Anonymous, at 4:29 PM  

  • Buen ejemplo y bien explicado. Un aplauso Darío que la verdad esto de los eventos y delegados es jodido de pillar. Un saludo desde España

    By Anonymous Anonymous, at 2:38 PM  

  • http://markonzo.edu clowning teck http://vzochat.com/en/blog/biofreeze http://chictini.com/tartsandwhores http://www.rottentomatoes.com/vine/showthread.php?p=17358565 http://jguru.com/guru/viewbio.jsp?EID=1534481 mariano http://community.momlogic.com/profiles/blogs/ashley-furniture-online

    By Anonymous Anonymous, at 2:22 PM  

Post a Comment

<< Home