Utilizar eventos

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 EventName As EventNameEventHandler
public event EventNameEventHandler EventName;
public:
    event EventNameEventHandler^ EventName;
  • El delegado de eventos para el evento EventName es EventNameEventHandler, con la siguiente firma:
Public Delegate Sub EventNameEventHandler(sender As Object, e As EventNameEventArgs)
public delegate void EventNameEventHandler(object sender, EventNameEventArgs e);
delegate void EventNameEventHandler(Object^ sender, EventNameEventArgs^ e);

Para consumir el evento EventName, el controlador de eventos debe tener la misma firma que el delegado de eventos:

Sub EventHandler(sender As Object, e As EventNameEventArgs)
End Sub
void EventHandler(object sender, EventNameEventArgs e) {}
void EventHandler(Object^ sender, EventNameEventArgs^ e) {}

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:

Sub Mouse_Moved(sender As Object, e As MouseEventArgs)
End Sub
void Mouse_Moved(object sender, MouseEventArgs e){}
void Mouse_Moved(Object^ sender, MouseEventArgs^ e){}

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

Conceptos

Eventos y delegados

Provocar un evento

Otros recursos

Controlar y provocar eventos