Cómo: Implementar eventos en una clase
Los siguientes procedimientos describen cómo implementar un evento en una clase. El primer procedimiento implementa un evento que no tiene datos asociados; utiliza las clases System.EventArgs y System.EventHandler para los datos de eventos y el controlador de delegados. El segundo procedimiento implementa un evento con datos personalizados; define las clases personalizadas para los datos de evento y el controlador del delegado de eventos.
Nota |
---|
En este tema se muestra cómo declarar y generar un evento en una clase.No se muestra cómo definir un controlador de eventos que consume ese evento.Para obtener información acerca de cómo consumir eventos, vea Utilizar eventos y Cómo: Provocar y utilizar eventos. |
Para obtener un ejemplo completo que muestra la generación y el control de eventos, vea Cómo: Provocar y utilizar eventos.
Para implementar un evento sin datos específicos del evento
Defina un miembro de evento público en la clase. Establezca el tipo del miembro de evento en un delegado System.EventHandler.
Public Class Countdown ' ... Public Event CountdownCompleted As EventHandler End Class
public class Countdown { // ... public event EventHandler CountdownCompleted; }
Incluya en la clase un método protegido que provoque el evento. Dé un nombre al método OnEventName. Provoque el evento dentro del método. Tenga en cuenta que el código de C# debe comprobar si el evento es nulo antes de generar el evento. Esto elimina la necesidad de controlar la excepción NullReferenceException que se produce cuando se genera un evento pero no se le ha adjuntado ningún controlador de eventos. Esta comprobación es necesaria en este caso porque la clase CountDown simplemente genera el evento pero no proporciona un controlador para él.
Public Class Countdown ' ... Public Event CountdownCompleted As EventHandler Protected Overridable Sub OnCountdownCompleted(e As EventArgs) RaiseEvent CountdownCompleted(Me, e) End Sub End Class
public class Countdown { public event EventHandler CountdownCompleted; protected virtual void OnCountdownCompleted(EventArgs e) { if (CountdownCompleted != null) CountdownCompleted(this, e); } }
Determine cuándo provocar el evento en la clase. Llame a OnEventName para provocar el evento.
Public Class Countdown Dim internalCounter As Integer = 0 ' ... Public Event CountdownCompleted As EventHandler Protected Overridable Sub OnCountdownCompleted(e As EventArgs) RaiseEvent CountdownCompleted(Me, e) End Sub Public Sub Decrement() internalCounter -= 1 If internalCounter = 0 OnCountdownCompleted(New EventArgs()) End If End Sub End Class
public class Countdown { int internalCounter = 0; // ... public event EventHandler CountdownCompleted; protected virtual void OnCountdownCompleted(EventArgs e) { if (CountdownCompleted != null) CountdownCompleted(this, e); } public void Decrement() { internalCounter--; if (internalCounter == 0) OnCountdownCompleted(new EventArgs()); } }
Para implementar un evento con datos específicos del evento
Defina una clase que proporcione los datos del evento. Dé un nombre a la clase EventNameArgs, derive la clase de System.EventArgs y agregue los miembros específicos del evento.
Public Class AlarmEventArgs : Inherits EventArgs Private nRings As Integer = 0 Private pressed As Boolean = False Private text As String = "The alarm is ringing!" ' Constructor. Public Sub New(ByVal snoozePressed As Boolean, ByVal nRings As Integer) Me.pressed = snoozePressed Me.nRings = nRings End Sub ' Properties. Public Property AlarmText() As String Get Return Me.text End Get Set Me.text = value End Set End Property Public ReadOnly Property NumRings() As Integer Get Return Me.nRings End Get End Property Public ReadOnly Property SnoozePressed() As Boolean Get Return Me.pressed End Get End Property End Class
public class AlarmEventArgs : EventArgs { private readonly int nRings = 0; private readonly bool pressed = false; private string text = "The alarm is ringing!"; // Constructor. public AlarmEventArgs(bool snoozePressed, int nRings) { this.pressed = snoozePressed; this.nRings = nRings; } // Properties. public string AlarmText { get { return text; } set { this.text = value; } } public int NumRings { get { return nRings; } } public bool SnoozePressed { get { return pressed; } } }
Declare un delegado para el evento. Dé un nombre al delegado EventNameEventHandler.
Public Delegate Sub AlarmEventHandler(sender As Object, e As AlarmEventArgs)
public delegate void AlarmEventHandler(object sender, AlarmEventArgs e);
Defina un miembro de evento público denominado EventName en la clase. Establezca el tipo del miembro de evento en el tipo de delegado de eventos.
Public Class AlarmClock ' ... Public Event Alarm As AlarmEventHandler End Class
public class AlarmClock { // ... public event AlarmEventHandler Alarm; }
Defina en la clase un método protegido que provoque el evento. Dé un nombre al método OnEventName. Provoque el evento dentro del método. Tenga en cuenta que el código de C# debe comprobar si el evento es nulo antes de generar el evento. Esto elimina la necesidad de controlar la excepción NullReferenceException que se produce cuando se genera un evento pero no se le ha adjuntado ningún controlador de eventos. Esta comprobación es necesaria en este caso porque la clase CountDown simplemente genera el evento pero no proporciona un controlador para él.
Public Class AlarmClock ' ... Public Event Alarm As AlarmEventHandler Protected Overridable Sub OnAlarm(e As AlarmEventArgs) RaiseEvent Alarm(Me, e) End Sub End Class
public class AlarmClock { // ... public event AlarmEventHandler Alarm; protected virtual void OnAlarm(AlarmEventArgs e) { if (Alarm != null) Alarm(this, e); } }
Determine cuándo provocar el evento en la clase. Llame a OnEventName para generar el evento y pase los datos específicos del evento usando EventNameEventArgs.
Public Class AlarmClock Public Sub Start ' ... System.Threading.Thread.Sleep(300) Dim e As AlarmEventArgs = New AlarmEventArgs(False, 0) OnAlarm(e) End Sub Public Event Alarm As AlarmEventHandler Protected Overridable Sub OnAlarm(e As AlarmEventArgs) RaiseEvent Alarm(Me, e) End Sub End Class
public class AlarmClock { public void Start() { // ... System.Threading.Thread.Sleep(300); AlarmEventArgs e = new AlarmEventArgs(false, 0); OnAlarm(e); } public event AlarmEventHandler Alarm; protected virtual void OnAlarm(AlarmEventArgs e) { if (Alarm != null) Alarm(this, e); } }
Ejemplo
En el ejemplo siguiente se define una clase DiskSpaceMonitor que usa un evento para generar una advertencia cada vez que el espacio disponible en disco está por debajo de un porcentaje que se define en un archivo de configuración. También se define una clase DiskSpaceWarningEventArgs para proporcionar datos personalizados sobre el espacio disponible en disco a los controladores de eventos.
Imports System.Collections.Specialized
Imports System.Configuration
Imports System.IO
Public Class DiskSpaceWarningEventArgs : Inherits EventArgs
Dim currentFreeSpace As Long
Dim currentTotalSpace As Long
Dim driveName As String
Public Sub New(name As String, freeSpace As Long, totalSpace As Long)
Me.driveName = name
Me.currentFreeSpace = freeSpace
Me.currentTotalSpace = totalSpace
End Sub
Public ReadOnly Property Name As String
Get
Return Me.driveName
End Get
End Property
Public ReadOnly Property FreeSpace As Long
Get
Return Me.currentFreeSpace
End Get
End Property
Public ReadOnly Property TotalSpace As Long
Get
Return Me.currentTotalSpace
End Get
End Property
End Class
Public Delegate Sub DiskSpaceWarningEventHandler(sender As Object, _
e As DiskSpaceWarningEventArgs)
Public Class DiskSpaceMonitor
Public Event DiskSpaceWarning As DiskSpaceWarningEventHandler
Private threshhold As Decimal
Public Sub New()
' Retrieve threshhold to fire event from configuration file.
Try
Dim settings As NameValueCollection = ConfigurationManager.AppSettings
Me.threshhold = CDec(settings.Item("Threshhold"))
' If there is no configuration file, provide a default value.
Catch e As ConfigurationErrorsException
Me.threshhold = 10d
Catch e As InvalidCastException
Me.threshhold = 10d
End Try
End Sub
Public Sub CheckFreeSpace
' Get drives present on system.
Dim drives() As DriveInfo = DriveInfo.GetDrives()
For Each drive As DriveInfo In drives
If drive.IsReady Then
If drive.TotalFreeSpace/drive.TotalSize <= Me.threshhold Then
OnDiskSpaceWarning(New DiskSpaceWarningEventArgs(drive.Name, _
drive.TotalFreeSpace, drive.TotalSize))
End If
End If
Next
End Sub
Protected Sub OnDiskSpaceWarning(e As DiskSpaceWarningEventArgs)
RaiseEvent DiskSpaceWarning(me, e)
End Sub
End Class
using System;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
public class DiskSpaceWarningEventArgs : EventArgs
{
private long currentFreeSpace;
private long currentTotalSpace;
private string driveName;
public DiskSpaceWarningEventArgs(string name, long freeSpace, long totalSpace)
{
this.driveName = name;
this.currentFreeSpace = freeSpace;
this.currentTotalSpace = totalSpace;
}
public string Name
{
get { return this.driveName; }
}
public long FreeSpace
{
get { return this.currentFreeSpace; }
}
public long TotalSpace
{
get { return this.currentTotalSpace; }
}
}
public delegate void DiskSpaceWarningEventHandler(object sender,
DiskSpaceWarningEventArgs e);
public class DiskSpaceMonitor
{
public event DiskSpaceWarningEventHandler DiskSpaceWarning;
private decimal threshhold;
public DiskSpaceMonitor()
{
// Retrieve threshhold to fire event from configuration file.
try
{
NameValueCollection settings = ConfigurationManager.AppSettings;
this.threshhold = Convert.ToDecimal(settings["Threshhold"]);
}
// If there is no configuration file, provide a default value.
catch (ConfigurationErrorsException)
{
this.threshhold = 10m;
}
catch (InvalidCastException)
{
this.threshhold = 10m;
}
}
public void CheckFreeSpace()
{
// Get drives present on system.
DriveInfo[] drives = DriveInfo.GetDrives();
foreach (DriveInfo drive in drives)
{
if (drive.IsReady)
{
if (drive.TotalFreeSpace/drive.TotalSize <= this.threshhold)
OnDiskSpaceWarning(new DiskSpaceWarningEventArgs(drive.Name,
drive.TotalFreeSpace, drive.TotalSize));
}
}
}
protected void OnDiskSpaceWarning(DiskSpaceWarningEventArgs e)
{
if (DiskSpaceWarning != null)
DiskSpaceWarning(this, e);
}
}
En lugar de usar la clase EventArgs para proporcionar datos de evento, en el ejemplo se define una clase de datos de evento personalizada denominada DiskSpaceWarningEventArgs. Proporciona a los controladores de eventos el nombre de la unidad, así como la cantidad de espacio libre y total disponible en la unidad. En el ejemplo también se define un delegado, DiskSpaceWarningEventHandler, que representa la firma del evento.
La clase DiskSpaceMonitor define el evento DiskSpaceWarning y proporciona un método OnDiskSpaceWarning que genera el evento. El método CheckFreeSpace llama a su vez al método OnDiskSpaceWarning cuando detecta que el espacio disponible en una unidad es menor o igual que un porcentaje que se define en un archivo de configuración.
Vea también
Tareas
Cómo: Provocar y utilizar eventos