Déclenchement d'un événement

Pour que votre classe déclenche un événement, vous devez fournir les trois éléments suivants :

  • une classe qui fournit les données d'événement ;

  • un délégué d'événement ;

  • la classe qui déclenche l'événement.

Définition d'une classe pour fournir les données d'événement

Par convention dans le .NET Framework, lorsqu'un événement est déclenché, il passe les données d'événement à ses gestionnaires d'événements. Les données d'événement sont fournies par la classe System.EventArgs ou par une classe qui en est dérivée.

Dans de nombreux cas, un événement n'a pas de données personnalisées ; le fait que l'événement ait été déclenché fournit toutes les informations requises par les gestionnaires d'événements. Dans ce cas, l'événement peut passer un objet EventArgs à ses gestionnaires. La classe EventArgs n'a qu'un seul membre, Empty, qui n'est pas hérité de System.Object. Il peut être utilisé pour instancier une nouvelle classe EventArgs.

Si un événement a des données personnalisées, il peut passer une instance d'une classe dérivée de EventArgs aux gestionnaires d'événements. En fonction des données précises que l'événement passe aux gestionnaires, il se peut que vous puissiez utiliser une classe de données d'événement existante dans le .NET Framework. Par exemple, si votre gestionnaire d'événements autorise l'annulation de l'action associée à l'événement, vous pouvez utiliser la classe CancelEventArgs.

Lorsque vous devez fournir des données personnalisées aux gestionnaires et qu'aucune classe existante n'est disponible, vous pouvez définir votre propre classe de données d'événement. Elle doit dériver de System.EventArgs. Par convention, cette classe est nommée EventNameEventArgs. L'exemple suivant illustre une telle classe de données d'événement personnalisée. Il définit une classe nommée AlarmEventArgs qui fournit deux éléments de données aux gestionnaires d'événements : la propriété Time en lecture seule, qui indique quand l'alarme se déclenche, et la propriété Snooze, qui indique si l'alarme doit se déclencher à nouveau après un intervalle désigné ou si les alarmes ultérieures doivent être annulées.

Public Class AlarmEventArgs : Inherits EventArgs
   Private alarmTime As Date
   Private snoozeOn As Boolean = True

   Public Sub New(time As Date)
      Me.alarmTime = time
   End Sub

   Public ReadOnly Property Time As Date
      Get
         Return Me.alarmTime
      End Get
   End Property

   Public Property Snooze As Boolean
      Get
         Return Me.snoozeOn
      End Get
      Set
         Me.snoozeOn = value
      End Set   
   End Property   
End Class
public class AlarmEventArgs : EventArgs
{
   private DateTime alarmTime;
   private bool snoozeOn = true;

   public AlarmEventArgs(DateTime time)
   {
      this.alarmTime = time;
   }

   public DateTime Time
   {
      get { return this.alarmTime; }
   }

   public bool Snooze
   {
      get { return this.snoozeOn; }
      set { this.snoozeOn = value; }
   }   
}
public ref class AlarmEventArgs : public EventArgs
{
private: 
   System::DateTime^ alarmTime;
   bool snoozeOn;

public:
   AlarmEventArgs(System::DateTime^ time) 
   {
      this->alarmTime = time;
      this->snoozeOn = true;
   }

   property DateTime^ Time 
   {
      System::DateTime^ get()
      { return this->alarmTime; }
   }

   property bool Snooze
   {
      bool get()
      { return this->snoozeOn; }
      void set(bool snooze)
      { this->snoozeOn = snooze; }
   }
};

Définition d'un délégué pour l'événement

Un délégué d'événement est utilisé pour définir la signature de l'événement. Un délégué d'événement particulier correspond généralement à une classe de données d'événement particulière. Par convention, dans le .NET Framework, les événements ont la signature EventName(sender, e), où sender est un Object qui fournit une référence à la classe ou la structure qui a déclenché l'événement, et e est un objet EventArgs ou un objet dérivé de EventArgs qui fournit les données d'événement. Généralement, la définition de délégué prend alors la forme EventNameHandler(sender, e).

Si vous utilisez une classe de données d'événement qui est déjà définie dans la bibliothèque de classes .NET Framework ou dans une bibliothèque tierce, il est possible qu'un délégué d'événement correspondant soit également défini dans cette bibliothèque. Par exemple, le délégué EventHandler peut être utilisé avec la classe EventArgs. De même, le délégué CancelEventHandler peut être utilisé avec la classe CancelEventArgs.

Si vous définissez une classe de données d'événement personnalisée, vous pouvez également définir un délégué personnalisé pour définir la signature d'événement, ou utiliser le délégué Action<T1, T2> générique.

L'exemple suivant définit un délégué d'événement nommé AlarmEventHandler.

Public Delegate Sub AlarmEventHandler(sender As Object, e As AlarmEventArgs)
public delegate void AlarmEventHandler(object sender, AlarmEventArgs e);
public delegate void AlarmEventHandler(System::Object^ sender, AlarmEventArgs^ e);

Définition d'une classe pour déclencher l'événement

La classe qui déclenche l'événement doit fournir la déclaration de l'événement et définir une méthode qui déclenche l'événement. De plus, elle doit fournir une certaine logique pour déclencher l'événement dans une propriété ou une méthode de classe.

Vous définissez un membre d'événement dans votre classe à l'aide du mot clé event en C# ou l'instruction Event en Visual Basic. Lorsque le compilateur rencontre une déclaration d'événement dans votre classe, il crée un membre privé, par exemple :

private EventNameHandler eh = null;

Le compilateur crée également les deux méthodes publiques add_EventName et remove_EventName. Ces méthodes sont des connexions d'événement qui permettent aux délégués d'être combinés au délégué d'événement eh ou d'en être supprimés. Les détails sont masqués dans le programmeur.

Notes

Dans d'autres langages que C# et Visual Basic 2005, le compilateur peut ne pas générer automatiquement le code correspondant à un membre d'événement et vous pouvez être amené à définir explicitement les connexions d'événement et le champ délégué privé.

L'exemple suivant déclare un événement nommé AlarmEvent. Il est extrait de l'exemple fourni pour une classe nommée Alarm dont le code source complet est indiqué ci-dessous. Notez qu'il a la signature du délégué AlarmEventHandler.

Event AlarmEvent As AlarmEventHandler
public event AlarmEventHandler AlarmEvent;
public:
   event AlarmEventHandler^ AlarmEvent; 

Une fois que vous avez défini votre implémentation d'événement, vous devez déterminer quand déclencher l'événement. Vous déclenchez l'événement en appelant la méthode protégée OnEventName dans la classe qui a défini l'événement, ou dans une classe dérivée. La méthode OnEventName déclenche alors l'événement.

Notes

La méthode protégée OnEventName permet également aux classes dérivées de substituer l'événement sans y attacher de délégué.Une classe dérivée doit toujours appeler la méthode OnEventName de la classe de base pour que les délégués inscrits puissent recevoir l'événement.

L'exemple suivant définit la méthode OnAlarmEvent, qui est chargée du déclenchement de l'événement AlarmEvent.

Protected Sub OnAlarmEvent(e As AlarmEventArgs)
   RaiseEvent AlarmEvent(Me, e)
End Sub  
protected void OnAlarmEvent(AlarmEventArgs e)
{
   AlarmEvent(this, e);
}  
protected:
   void OnAlarmEvent(AlarmEventArgs^ e)
   {
      AlarmEvent(this, e);
   }

L'exemple suivant définit une méthode nommée Set qui contient la logique à utiliser pour déclencher l'événement en appelant la méthode OnAlarmEvent. Si les heures et les minutes de l'heure de l'alarme sont égales aux heures et aux minutes de l'heure actuelle, la méthode Set instancie un objet AlarmEventArgs et lui fournit l'heure à laquelle l'alarme s'est déclenchée. Une fois l'exécution des gestionnaires d'événements terminée, elle vérifie la valeur de la propriété Snooze. Si Snooze a la valeur false, aucun autre événement d'alarme ne doit être déclenché. La méthode Set peut se terminer. Si Snooze a la valeur true, l'heure à laquelle l'alarme doit être déclenchée est incrémentée de la valeur de la propriété Interval.

Public Sub [Set]()
   Do
      System.Threading.Thread.Sleep(2000)
      Dim currentTime As DateTime = Date.Now
      ' Test whether it is time for the alarm to go off.
      If currentTime.Hour = alarmTime.Hour And _
         currentTime.Minute = AlarmTime.Minute Then
         Dim args As New AlarmEventArgs(currentTime)
         OnAlarmEvent(args)
         If args.Snooze = False Then 
            Exit Sub
         Else
            Me.alarmTime = Me.alarmTime.AddMinutes(Me.interval)
         End If      
      End If          
   Loop
End Sub 
public void Set()
{
   while (true) {
      System.Threading.Thread.Sleep(2000);
      DateTime currentTime = DateTime.Now;
      // Test whether it is time for the alarm to go off.
      if (currentTime.Hour == alarmTime.Hour && 
          currentTime.Minute == alarmTime.Minute)
      {    
         AlarmEventArgs args = new AlarmEventArgs(currentTime);
         OnAlarmEvent(args);
         if (! args.Snooze) 
            return;
         else
            this.alarmTime = this.alarmTime.AddMinutes(this.interval);
      }
   }
} 
void Set()
{
   do {
      Thread::Sleep(2000);
      System::DateTime^ currentTime = DateTime::Now;
      // Test whether it's time for the alarm to go off.
      if (currentTime->Hour == alarmTime->Hour && currentTime->Minute == alarmTime->Minute)
      {
         AlarmEventArgs^ args = gcnew AlarmEventArgs(currentTime);
         OnAlarmEvent(args);
         if (args->Snooze == false)
            return;
         else
            this->alarmTime = this->alarmTime->AddMinutes(this->interval);
      }
   } while (true);
}

L'exemple suivant inclut la totalité du code source pour la classe Alarm.

Public Class Alarm
   Private alarmTime As Date
   Private interval As Integer = 10

   Event AlarmEvent As AlarmEventHandler

   Public Sub New(time As Date)
      Me.New(time, 10)
   End Sub

   Public Sub New(time As Date, interval As Integer)
      Me.alarmTime = time
      Me.interval = interval
   End Sub

   Public Sub [Set]()
      Do
         System.Threading.Thread.Sleep(2000)
         Dim currentTime As DateTime = Date.Now
         ' Test whether it is time for the alarm to go off.
         If currentTime.Hour = alarmTime.Hour And _
            currentTime.Minute = AlarmTime.Minute Then
            Dim args As New AlarmEventArgs(currentTime)
            OnAlarmEvent(args)
            If args.Snooze = False Then 
               Exit Sub
            Else
               Me.alarmTime = Me.alarmTime.AddMinutes(Me.interval)
            End If      
         End If          
      Loop
   End Sub 

   Protected Sub OnAlarmEvent(e As AlarmEventArgs)
      RaiseEvent AlarmEvent(Me, e)
   End Sub  
End Class
public class Alarm
{
   private DateTime alarmTime;
   private int interval = 10;

   public event AlarmEventHandler AlarmEvent;

   public Alarm(DateTime time) : this(time, 10)
   {
   }

   public Alarm(DateTime time, int interval)
   {
      this.alarmTime = time;
      this.interval = interval;
   }

   public void Set()
   {
      while (true) {
         System.Threading.Thread.Sleep(2000);
         DateTime currentTime = DateTime.Now;
         // Test whether it is time for the alarm to go off.
         if (currentTime.Hour == alarmTime.Hour && 
             currentTime.Minute == alarmTime.Minute)
         {    
            AlarmEventArgs args = new AlarmEventArgs(currentTime);
            OnAlarmEvent(args);
            if (! args.Snooze) 
               return;
            else
               this.alarmTime = this.alarmTime.AddMinutes(this.interval);
         }
      }
   } 

   protected void OnAlarmEvent(AlarmEventArgs e)
   {
      AlarmEvent(this, e);
   }  
}
public ref class Alarm 
{
private:
   System::DateTime^ alarmTime;
   int interval;

public:
   event AlarmEventHandler^ AlarmEvent; 
   Alarm(System::DateTime^ time) : alarmTime(time), interval(10) { };
   Alarm(System::DateTime^ time, int interval) : alarmTime(time), interval(interval) {};

   void Set()
   {
      do {
         Thread::Sleep(2000);
         System::DateTime^ currentTime = DateTime::Now;
         // Test whether it's time for the alarm to go off.
         if (currentTime->Hour == alarmTime->Hour && currentTime->Minute == alarmTime->Minute)
         {
            AlarmEventArgs^ args = gcnew AlarmEventArgs(currentTime);
            OnAlarmEvent(args);
            if (args->Snooze == false)
               return;
            else
               this->alarmTime = this->alarmTime->AddMinutes(this->interval);
         }
      } while (true);
   }

protected:
   void OnAlarmEvent(AlarmEventArgs^ e)
   {
      AlarmEvent(this, e);
   }
};

Voir aussi

Tâches

Comment : déclencher et utiliser des événements

Comment : implémenter des événements dans votre classe

Concepts

Événements et délégués

Autres ressources

Gestion et déclenchement d'événements