Utilizar eventos
Actualización: noviembre 2007
Para consumir un evento en una aplicación, debe proporcionar un controlador de eventos (método de control de eventos) que ejecute la lógica del programa en respuesta al evento, y que registre el controlador de eventos en el origen del evento. Este proceso se denomina conexión de eventos. Los diseñadores visuales de formularios Windows Forms y formularios Web Forms disponen de herramientas para la programación rápida de aplicaciones (RAD) que simplifican u ocultan los detalles de la conexión de eventos.
En este tema se describe el modelo general de control de eventos. Para obtener información general sobre el modelo de eventos de .NET Framework, vea Eventos y delegados. Para obtener más información sobre el modelo de eventos en formularios Windows Forms, vea Cómo: Consumir eventos en una aplicación de formularios Windows Forms. Para obtener más información sobre el modelo de eventos en formularios Web Forms, vea Cómo: Consumir eventos en una aplicación de formularios Web Forms.
Patrón de eventos
Los detalles sobre el cableado de eventos son diferentes tanto en los formularios Windows Forms como en los formularios Web Forms debido a los niveles diferentes de compatibilidad proporcionados por diferentes herramientas RAD. Sin embargo, ambos escenarios siguen el mismo modelo de evento, que tiene las siguientes características:
Una clase que provoca un evento denominado EventName tiene el siguiente miembro:
public event EventNameEventHandler EventName;
Public Event EventName As EventNameEventHandler
El delegado de eventos para el evento EventName es EventNameEventHandler, con la siguiente firma:
public delegate void EventNameEventHandler(object sender, EventNameEventArgs e);
Public Delegate Sub EventNameEventHandler(sender As Object, e As EventNameEventArgs)
Para consumir el evento EventName, el controlador de eventos debe tener la misma firma que el delegado de eventos:
void EventHandler(object sender, EventNameEventArgs e) {}
Sub EventHandler(sender As Object, e As EventNameEventArgs)
Nota: |
---|
En .NET Framework, un delegado de eventos se denomina EventNameEventHandler, mientras que en la documentación, controlador de eventos hace referencia a un método de control de eventos. La razón de la utilización de este esquema de nombres es que un delegado EventNameEventHandler apunta al controlador de eventos (el método) que en realidad controla el evento. |
Cuando un evento no tiene ningún dato asociado, la clase que provoca el evento utiliza System.EventHandler como delegado y System.EventArgs para los datos del evento. Los eventos que tienen datos asociados utilizan clases que se derivan de EventArgs para ese tipo de datos de evento y el tipo de delegado de evento correspondiente. Por ejemplo, si se desea controlar un evento MouseUp en una aplicación de Windows Forms, la clase de datos de evento es MouseEventArgs y el delegado de evento es MouseEventHandler. Observe que varios eventos de mouse utilizan una clase común de datos de evento y un delegado de evento común, por lo que el esquema de nombres no coincide exactamente con la convención descrita anteriormente. En el caso de los eventos del mouse, el controlador de eventos debe tener la firma siguiente:
void Mouse_Moved(object sender, MouseEventArgs e){}
Sub Mouse_Moved(sender As Object, e As MouseEventArgs)
El remitente y los parámetros de argumentos de eventos proporcionan detalles adicionales sobre el evento del mouse al controlador de eventos. El objeto de remitente indica qué fue lo que provocó el evento. El parámetro MouseEventArgs proporciona detalles sobre el movimiento del mouse que provocó el evento. Muchos orígenes de eventos proporcionan datos adicionales para el evento y muchos controladores de eventos utilizan los datos específicos del evento para procesar el evento en cuestión. Para obtener un ejemplo que muestre cómo provocar y controlar eventos con datos específicos del evento, vea Cómo a: Provocar y utilizar eventos.
Nota: |
---|
Los eventos también se provocan fuera del contexto de las interfaces de usuario y, de hecho, .NET Framework incluye muchas clases que no son de interfaz de usuario y que provocan eventos. No obstante, todos los eventos siguen el patrón aquí descrito. |
Para obtener información sobre cómo provocar los eventos de una clase, vea Provocar un evento.
Eventos estáticos y dinámicos
.NET Framework permite a los suscriptores registrarse para la notificación de eventos estática o dinámicamente. Los controladores de eventos estáticos son efectivos durante toda la vida de la clase cuyos eventos controlan. Este es el método más común de controlar eventos. Los controladores de eventos dinámicos se activan y desactivan explícitamente durante la ejecución de un programa, normalmente en respuesta a alguna lógica condicional del programa. Por ejemplo, pueden utilizarse si las notificaciones de eventos solo son necesarias en condiciones específicas o si una aplicación proporciona varios controladores de eventos y las condiciones en tiempo de ejecución determinan cuál es el que debe utilizarse.
El método EventInfo.AddEventHandler agrega controladores de eventos dinámicos y el método EventInfo.RemoveEventHandler los desactiva. Cada lenguaje proporciona también sus propias características para controlar eventos de forma dinámica. En el ejemplo siguiente se define una clase TemperatureMonitor que provoca un evento TemperatureTheshold siempre que la temperatura alcanza un umbral predefinido. Un controlador de eventos suscrito a este evento se activa y se desactiva durante la ejecución del programa.
public class TemperatureEventArgs : Inherits EventArgs
Private oldTemp As Decimal
Private newTemp As Decimal
Public ReadOnly Property OldTemperature As Decimal
Get
Return Me.oldTemp
End Get
End Property
Public ReadOnly Property NewTemperature As Decimal
Get
Return Me.newTemp
End Get
End Property
Public Sub New(oldTemp As Decimal, newTemp As Decimal)
Me.oldTemp = oldTemp
Me.newTemp = newTemp
End Sub
End Class
Public Delegate Sub TemperatureEventHandler(sender As Object, _
ev As TemperatureEventArgs)
Public Class TemperatureMonitor
Private currentTemperature As Decimal
Private threshholdTemperature As Decimal
Public Event TemperatureThreshold As TemperatureEventHandler
Public Sub New(threshHold As Decimal)
Me.threshholdTemperature = threshHold
End Sub
Public Sub SetTemperature(newTemperature As Decimal)
If (Me.currentTemperature > threshholdTemperature And _
newTemperature <= Me.threshholdTemperature) Or _
(Me.CurrentTemperature < Me.threshholdTemperature And _
newTemperature >= Me.threshholdTemperature) Then
OnRaiseTemperatureEvent(newTemperature)
End If
Me.currentTemperature = newTemperature
End Sub
Public Function GetTemperature() As Decimal
Return Me.currentTemperature
End Function
Protected Overridable Sub OnRaiseTemperatureEvent(newTemperature As Decimal)
RaiseEvent TemperatureThreshold(Me, New TemperatureEventArgs(Me.currentTemperature, _
newTemperature))
End Sub
End Class
Public Module Example
Public Sub Main()
Dim tempMon As New TemperatureMonitor(32d)
tempMon.SetTemperature(33)
Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", _
tempMon.GetTemperature())
tempMon.SetTemperature(32)
Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", _
tempMon.GetTemperature())
' Add event handler dynamically using Visual Basic syntax.
AddHandler tempMon.TemperatureThreshold, AddressOf TempMonitor
tempMon.SetTemperature(33)
Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", _
tempMon.GetTemperature())
tempMon.SetTemperature(34)
Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", _
tempMon.GetTemperature())
tempMon.SetTemperature(32)
Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", _
tempMon.GetTemperature())
' Remove event handler dynamically using Visual Basic syntax.
RemoveHandler tempMon.TemperatureThreshold, AddressOf TempMonitor
tempMon.SetTemperature(31)
Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", _
tempMon.GetTemperature())
tempMon.SetTemperature(35)
Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", _
tempMon.GetTemperature())
End Sub
Private Sub TempMonitor(sender As Object, e As TemperatureEventArgs)
Console.WriteLine(" ***Warning: Temperature is changing from {0} to {1}.", _
e.OldTemperature, e.NewTemperature)
End Sub
End Module
' The example displays the following output:
' Current temperature is 33 degrees Fahrenheit.
' Current temperature is 32 degrees Fahrenheit.
' Current temperature is 33 degrees Fahrenheit.
' Current temperature is 34 degrees Fahrenheit.
' ***Warning: Temperature is changing from 34 to 32.
' Current temperature is 32 degrees Fahrenheit.
' Current temperature is 31 degrees Fahrenheit.
' Current temperature is 35 degrees Fahrenheit.
using System;
public class TemperatureEventArgs : EventArgs
{
private decimal oldTemp;
private decimal newTemp;
public decimal OldTemperature
{
get { return this.oldTemp; }
}
public decimal NewTemperature
{
get { return this.newTemp; }
}
public TemperatureEventArgs(decimal oldTemp, decimal newTemp)
{
this.oldTemp = oldTemp;
this.newTemp = newTemp;
}
}
public delegate void TemperatureEventHandler(object sender, TemperatureEventArgs ev);
public class TemperatureMonitor
{
private decimal currentTemperature;
private decimal threshholdTemperature;
public event TemperatureEventHandler TemperatureThreshold;
public TemperatureMonitor(decimal threshhold)
{
this.threshholdTemperature = threshhold;
}
public void SetTemperature(decimal newTemperature)
{
if ( (this.currentTemperature > this.threshholdTemperature &&
newTemperature <= this.threshholdTemperature) ||
(this.currentTemperature < this.threshholdTemperature &&
newTemperature >= this.threshholdTemperature) )
OnRaiseTemperatureEvent(newTemperature);
this.currentTemperature = newTemperature;
}
public decimal GetTemperature()
{
return this.currentTemperature;
}
protected virtual void OnRaiseTemperatureEvent(decimal newTemperature)
{
// Raise the event if it has subscribers.
if (TemperatureThreshold != null)
TemperatureThreshold(this, new TemperatureEventArgs(this.currentTemperature,
newTemperature));
}
}
public class Example
{
public static void Main()
{
Example ex = new Example();
ex.MonitorTemperatures();
}
public void MonitorTemperatures()
{
TemperatureMonitor tempMon = new TemperatureMonitor(32);
tempMon.SetTemperature(33);
Console.WriteLine("Current temperature is {0} degrees Fahrenheit.",
tempMon.GetTemperature());
tempMon.SetTemperature(32);
Console.WriteLine("Current temperature is {0} degrees Fahrenheit.",
tempMon.GetTemperature());
// Add event handler dynamically using C# syntax.
tempMon.TemperatureThreshold += this.TempMonitor;
tempMon.SetTemperature(33);
Console.WriteLine("Current temperature is {0} degrees Fahrenheit.",
tempMon.GetTemperature());
tempMon.SetTemperature(34);
Console.WriteLine("Current temperature is {0} degrees Fahrenheit.",
tempMon.GetTemperature());
tempMon.SetTemperature(32);
Console.WriteLine("Current temperature is {0} degrees Fahrenheit.",
tempMon.GetTemperature());
// Remove event handler dynamically using C# syntax.
tempMon.TemperatureThreshold -= this.TempMonitor;
tempMon.SetTemperature(31);
Console.WriteLine("Current temperature is {0} degrees Fahrenheit.",
tempMon.GetTemperature());
tempMon.SetTemperature(35);
Console.WriteLine("Current temperature is {0} degrees Fahrenheit.",
tempMon.GetTemperature());
}
private void TempMonitor(object sender, TemperatureEventArgs e)
{
Console.WriteLine(" ***Warning: Temperature is changing from {0} to {1}.",
e.OldTemperature, e.NewTemperature);
}
}
// The example displays the following output:
// Current temperature is 33 degrees Fahrenheit.
// Current temperature is 32 degrees Fahrenheit.
// Current temperature is 33 degrees Fahrenheit.
// Current temperature is 34 degrees Fahrenheit.
// ***Warning: Temperature is changing from 34 to 32.
// Current temperature is 32 degrees Fahrenheit.
// Current temperature is 31 degrees Fahrenheit.
// Current temperature is 35 degrees Fahrenheit.
Vea también
Tareas
Cómo: Consumir eventos en una aplicación de formularios Web Forms
Cómo: Consumir eventos en una aplicación de formularios Windows Forms