Para disparar un evento en C# se utilizan los delegados
Un evento es la forma que tiene una clase para notificar
a los clientes de la clase que ha ocurrido algo digno de capturar en un método en el que
se inserta código para tratarlo. Su utilización más habitual se produce en las
interfaces gráficas; es de todos conocido el evento click que se ejecuta al
pulsar un botón de una interfaz gráfica.
Los eventos proporcionan
un medio adecuado para que los objetos puedan reaccionar a cambios de estado
que pueden resultar útiles para los clientes del objeto.
En primer lugar, creamos
un delegado que manejará los eventos de cambio en al introducir objetos en una lista.
public delegate void ManejadorEventosCambio(object
sender, EventArgs e);
En el programa principal Main(), creamos un objeto de una
clase Lista que es la que contiene el evento
public static void Main()
{
// Crea
una nueva lista.
EventoCambiaLista lista = new EventoCambiaLista();
Después se crea un objeto que escucha los eventos de
cambio de la lista.
EscuchaEvento escuchador = new EscuchaEvento(lista);
EscuchaEvento es
un método que pasa por referencia un objeto lista de la clase EventoCambiaLista. Este
método lo añade al delegado de la siguiente forma:
Lista.Cambio
+= new ManejadorEventosCambio(ListaCambio);
La definición del método completo es la siguiente:
public EscuchaEvento(EventoCambiaLista lista)
{
Lista = lista;
//Se
añade "ListaCambio" al evento Cambio de Lista.
Lista.Cambio += new ManejadorEventosCambio(ListaCambio);
}
Si añadimos un objeto a la lista, en el programa
principal llamaremos a:
lista.Add("Objeto 1");
Al ejecutar esta línea, el programa ejecuta
el método Add definido de la siguiente manera:
public override int Add(object valor)
{
int i = base.Add(valor);
HayCambio(EventArgs.Empty);
return i;
}
Cuando se invoca al evento HayCambio ejecuta
el método del mismo nombre
Definido así:
//Invoca
el evento Cambio; Se llama cuando la lista cambia
protected virtual void HayCambio(EventArgs e)
{
if (Cambio != null)
Cambio(this, e);
}
En el caso de que haya un cambio llama a
ListaCambio a través de la instrucción Cambio(this,e); El evento ListaCambio se dispara cada vez
que cambia la lista.
private void ListaCambio(object sender, EventArgs e)
{
Console.WriteLine("Esto
se llama cuando se dispara el evento.");
}
Que muestra en
pantalla un texto. Este método es el que debe contener el código que deseamos
ejecutar cuando se dispara un evento, en este caso muestra en pantalla el texto
"Esto se llama cuando se dispara el
evento."
A continuación limpiamos la
lista ejecutando:
lista.Clear();
Esto ejecuta el método Clear definido de la
siguiente manera:
public override void Clear()
{
base.Clear();
HayCambio(EventArgs.Empty);
}
Al ejecutar la llamada a
HayCambio dispara de nuevo el evento repitiendo la misma secuencia de
operaciones que la explicada
anteriormente para lista.Add("Objeto 1"); Finalmente se llama a
escuchador.Desvincula(); para desvincular la lista del evento. Esta acción ejecuta
este método
public void Desvincula()
{
//
Desvincula el evento y elimina la lista.
Lista.Cambio -= new ManejadorEventosCambio(ListaCambio);
Lista = null;
}
A continuación
el programa completo:
using System;
namespace Colecciones
{
using System.Collections;
// Un
tipo de delegado para conectar las notificaciones de cambios.
public delegate void ManejadorEventosCambio(object sender, EventArgs e);
//Una
clase que funciona igual que ArrayList, pero envía notificaciones de eventos
cada vez que cambia la lista.
public class EventoCambiaLista : ArrayList
{
//Un
evento que los clientes pueden usar para notificar cuando cambian los elementos
de la lista.
public event ManejadorEventosCambio Cambio;
//Invoca
el evento Cambio; Se llama cuando la lista cambia
protected virtual void HayCambio(EventArgs e)
{
if (Cambio != null)
Cambio(this, e);
}
//Sobrecarga
algunos métodos que pueden cambiar la lista, invoca el evento después de cada
llamada
public override int Add(object valor)
{
int i = base.Add(valor);
HayCambio(EventArgs.Empty);
return i;
}
public override void Clear()
{
base.Clear();
HayCambio(EventArgs.Empty);
}
public override object this[int indice]
{
set
{
base[indice] = value;
HayCambio(EventArgs.Empty);
}
}
}
}
namespace TesteaEventos
{
using Colecciones;
class EscuchaEvento
{
private EventoCambiaLista Lista;
public EscuchaEvento(EventoCambiaLista lista)
{
Lista = lista;
//Se
añade "ListaCambio" al evento Cambio de Lista.
Lista.Cambio += new ManejadorEventosCambio(ListaCambio);
}
// Se
llamará cada vez que cambie la lista.
private void ListaCambio(object sender, EventArgs e)
{
Console.WriteLine("Esto
se llama cuando se dispara el evento.");
}
public void Desvincula()
{
//
Desvincula el evento y elimina la lista.
Lista.Cambio -= new ManejadorEventosCambio(ListaCambio);
Lista = null;
}
}
class Testea
{
//
Programa principal. Testea el evento de la clase EventoCambiaLista.
public static void Main()
{
// Crea
una nueva lista.
EventoCambiaLista lista = new EventoCambiaLista();
// Crea
una clase que escucha los eventos de cambio de la lista.
EscuchaEvento escuchador = new EscuchaEvento(lista);
// Añade
y elimina objetos de la lista.
lista.Add("Objeto 1");
lista.Clear();
escuchador.Desvincula();
}
}
}
Eventos y herencia
Si de un componente se pueden derivar clases, es posible que haya problemas con los eventos. Como los eventos
sólo se pueden invocar desde la clase que los declaró, las clases derivadas no
pueden invocar eventos declarados dentro de la clase base.
Pero hay veces que es mejor dar a la clase derivada la libertad de invocar
el evento. Para hacer esto se crea un método de invocación protegido para el
evento. Luego se llama a este método y
así las clases derivadas pueden invocar
el evento. El método que invoca se declarar como virtual para tener mayor
flexibilidad.
Eventos en interfaces
Un evento también se puede colocar en una interfaz. Cuando se implementa la
interfaz, la clase que la implementa debe suministrar el evento correspondiente
en la clase que implementa la interfaz.
Requisitos de eventos para .NET Framework
El tipo delegado utilizado para un evento debe aceptar dos parámetros: un
parámetro "origen del objeto" que indique el origen del evento y un
parámetro "e" que encapsule cualquier información adicional acerca
del evento. El tipo del parámetro "e" debe derivarse de la
clase EventArgs. Para eventos que no utilizan información
adicional, .NET Framework tiene ya definido un tipo delegado apropiado: EventHandler.
A continuación una versión modificada del ejemplo anterior:
Al ejecutar el programa principal, sigue una secuencia similar a la del
primer programa solo que ahora utiliza el delegado perteneciente al framework
llamado EventHandler por lo que no es
necesario crear un delegado ManejadorEventosCambio como en el primer
ejemplo.
El
funcionamiento del programa es idéntico.
Aquí el código completo del programa:
using System;
namespace MiColeccion
{
using System.Collections;
//Esta
clase funciona como ArrayList, pero envía notificaciones de eventos cada vez
que cambia la lista:
public class EventoCambiaLista : ArrayList
{
//Un
evento que los clientes pueden utilizar para ser notificado cada vez que
cambien los elementos de la lista:
public event EventHandler Cambio;
//Invoca
el evento Cambio; Cuando hay un cambio en la lista:
protected virtual void HayCambio(EventArgs e)
{
if (Cambio != null)
Cambio(this, e);
}
//Sobreescribe
algunos métodos que pueden cambiar la lista; Invoca el evento
public override int Add(object valor)
{
int i = base.Add(valor);
HayCambio(EventArgs.Empty);
return i;
}
public override void Clear()
{
base.Clear();
HayCambio(EventArgs.Empty);
}
public override object this[int indice]
{
set
{
base[indice] = value;
HayCambio(EventArgs.Empty);
}
}
}
}
namespace TesteaEventos
{
using MiColeccion;
class EscuchaEvento
{
private EventoCambiaLista Lista;
public EscuchaEvento(EventoCambiaLista lista)
{
Lista = lista;
//Añade
"ListaCambio" al evento de cambio en "Lista";
Lista.Cambio += new EventHandler(ListaCambio);
}
// Se
llamará cada vez que cambie la lista:
private void ListaCambio(object sender, EventArgs e)
{
Console.WriteLine("Se
llama cuando se dispara el evento.");
}
public void Detach()
{
//Saca
el evento y lo elimina de la lista
Lista.Cambio -= new EventHandler(ListaCambio);
Lista = null;
}
}
class Testeo
{
//
Testea la clase EventoCambiaLista:
public static void Main()
{
// Crea
una nueva lista
EventoCambiaLista lista = new EventoCambiaLista();
// Crea
una clase que escucha el evento cambio de la lista:
EscuchaEvento escuchador = new EscuchaEvento(lista);
// Añade
y elimina objetos de la lista:
lista.Add("objeto 1");
lista.Clear();
escuchador.Detach();
}
}
}
No hay comentarios:
Publicar un comentario