Eventos y Comunicación entre Formularios en Visual C# Express

 

Tenía la siguiente duda: Si tengo una aplicación de múltiples ventanas, con ninguna MDI ¿cómo hago para que las demás sepan lo que está sucediendo en la venta activa? Por ejemplo, al presionar un botón en la ventana 2, quiero que cambie un texto en la ventana 1. 

Hallé una posible respuesta aquí: http://systemtak.blogspot.com/2009/09/eventos-delegados-en-c.html.

Se tienen dos ventanas, o formularios, llamados Form1 y Form2. Desde Form1 se declara una instancia de la clase Form2 y a través de ella se puede carga la ventana Form2 y controlar su comportamiento ya que de esta forma Form1 es el "padre" o "parent" de Form2. La ventana padre se comunica con la ventana hijo o "child" a través de sus métodos públicos tal y como está explicado aquí (con la diferencia que Form1 no es MDI).

La instancia de Form2 se llama miForm en este ejemplo.

 

Lo malo es que Systemtak no explica qué sucede en el caso de que tenga más de dos ventanas, se quiera que se comuniquen entre sí y que una sepa lo que está pasando en la otra (si se apretó un botón por ejemplo) sin necesidad que sean hijas de Form1.

La solución es muy sencilla, se trata de que la ventana que envía los mensajes tenga una instancia pública a sí misma a la que se puede acceder desde las otras ventanas. Esta ventana será Form3, mientras que Form2 será hija de Form1. Para construir el ejemplo se crea un proyecto de WinForm en Visual C# Studio Express con tres formularios (o ventanas): Form1, Form2 y Form3.

Form3 (quien envía mensajes a las otras dos ventanas) tiene dos botones (button1 y button2) que al presionarlos harán que cambie el texto en label1 (ubicado en Form1) y en label2 (ubicado en Form2). El código es:

Se tienen dos delegados, cada uno vinculado a un evento que se dispara al presionar cada botón. Además Form3 tiene su instancia pública. Todo lo que queramos ver desde las otras ventanas debe ser público. Ahora el siguiente paso es decirle a Form1 y Form2 que reciban los eventos, o mejor dicho, que se suscriban a ellos. Esto se hace mediante la instancia pública de Form3.

El código para Form1 (padre de Form2) es:

 

En el método Load de Form1 éste se está suscribiendo a los eventos de Form3 y Form2. Cada evento tiene asociado un método dentro de Form1 que le dice qué debe hacer. La única condición está en que el método debe tener la misma firma (misma cantidad, tipo de parámetros y valor devuelto) que el delegado de cada evento.

Form2 tiene además dos botones que incrementarán o decrementarán el valor de una variable, y éste valor se verá en el texto de la ventana Form1. Esto lo maneja a través del evento "Contar". Además Form2 se está suscribiendo al evento de Form3 "Otro Evento" y asociándole el método que cambiará el texto en su label2. El código de Form2 es:

 

Si se desea que Form1 sea formulario MDI,  y que Form2 y Form3 estén contenidos en él hay que añadir una instancia pública de Form1 para que sea accesible desde Form3. Dado que la instancia de Form2 está declarada en Form1, se le puede ordenar que esté contenido en Form1 desde Form1 (que tendrá su propiedad IsMdiContainer = True). En cambio a Form3 tendrá que ordenársele que esté contenido en Form1 a través de la instancia pública de Form1.

El trocito de código que se debe añadir a Form1 es:

 

Y en Form3 sólo se añade este trocito:

 

En el zip que dejo para descargar está el proyecto con el código para Form1, Form2 y Form3. Además de otro ejemplo con Form1 como Mdi y otro usando métodos anónimos.