Disparar um evento

Se desejar que sua classe para elevar um evento, você deve fornecer três elementos a seguir:

  • Uma classe que fornece dados de evento.

  • Um delegado do evento.

  • A classe que gera o evento.

Definir uma classe para fornecer dados de evento

Por convenção na .NET Framework, quando um evento é gerado, ele passa os dados de evento para seus manipuladores de eventos. Os dados do evento são fornecidos pelo System.EventArgs de classe ou por uma classe que é derivado dele.

Em geral, um evento não tem nenhum dados personalizados; o fato de que o evento foi disparado fornece todas as informações que necessitam de manipuladores de eventos. Nesse caso, o evento pode passar um EventArgs o objeto para seus manipuladores. O EventArgs classe tem apenas um único membro, Empty, ou seja não herdadas do System.Object. Ele pode ser usado para instanciar uma nova EventArgs classe.

Se um evento tem dados personalizados, ele pode passar uma instância de uma classe derivada de EventArgs a manipuladores de eventos. Dependendo dos dados precisos o evento passa para manipuladores, talvez você possa usar uma classe de dados de eventos existente na .NET Framework. Por exemplo, se o seu manipulador de eventos permite que a ação associada ao evento a ser cancelada, você pode usar o CancelEventArgs classe.

Quando você precisa fornecer dados personalizados para manipuladores e uma classe existente não estiver disponível, você pode definir sua própria classe de dados de evento. Ele deve derivar de System.EventArgs. Por convenção, essa classe é nomeada EventNameEventArgs. O exemplo a seguir ilustra como uma classe de dados de evento personalizado. Ele define uma classe chamada AlarmEventArgs que fornece dois itens de dados para manipuladores de eventos: o somente leitura Time propriedade, que indica quando o alarme entrou desativada; e o Snooze propriedade, que indica se o alarme deve apagam novamente após um intervalo designado ou se os alarmes futuros devem ser cancelados.

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; }
   }
};

Definindo um delegado para o evento.

Um delegado do evento é usado para definir a assinatura do evento. Normalmente, um delegado de determinado evento corresponde a uma classe de dados de evento específico. Por convenção, os eventos do .NET Framework tem a assinatura EventName(sender, e), onde sender é um Object que fornece uma referência para a classe ou estrutura que disparou o evento, e e é um EventArgs objeto ou um objeto derivado de EventArgs que fornece dados do evento. Em seguida, a definição de delegado normalmente assume a forma EventNameHandler(sender, e).

Se você estiver usando uma classe de dados do evento já está definida na.NET Framework class library ou em uma biblioteca de terceiros, é provável que um representante de evento correspondente também é definido nessa biblioteca. Por exemplo, o EventHandler representante pode ser usado juntamente com o EventArgs classe. Da mesma forma, o CancelEventHandler representante pode ser usado juntamente com o CancelEventArgs classe.

Se você define uma classe de dados de evento personalizado, você também pode definir um delegado personalizado para definir a assinatura do evento ou você pode usar a genérica Action<T1, T2> delegar.

O exemplo a seguir define um delegado de evento chamado 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);

Definir uma classe para disparar o evento

A classe que gera o evento deve fornecer a declaração de evento e definir um método que gera o evento. Além disso, ele deve fornecer alguma lógica para disparar o evento em uma propriedade de classe ou método.

Você define um membro de eventos em sua classe usando o event palavra-chave em C# ou o Event instrução em Visual Basic. Quando o compilador encontra uma declaração de evento na sua classe, ele cria um membro particular, como:

private EventNameHandler eh = null;

O compilador também cria dois métodos públicos, add_EventName e remove_EventName. Esses métodos são ganchos de eventos que permitem que representantes sejam combinados ou removidos do representante do evento eh. Os detalhes são ocultados do programador.

Dica

Em linguagens diferentes de C# e Visual Basic 2005, o compilador pode não gerar automaticamenteo o código correspondente a um membro de evento, e você talvez precise definir explicitamente os ganchos de evento e o campo particular de representantes.

O exemplo a seguir declara um evento chamado AlarmEvent. Ele é extraído o exemplo de uma classe denominada Alarm cujo código-fonte completo é mostrado abaixo. Observe que ela tem a assinatura da AlarmEventHandler delegar.

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

Após você definir sua implementação de evento, você deve determinar quando gerar o evento. Gerar o evento, chamando o protegido OnEventName método na classe que definiu o evento ou em uma classe derivada. O OnEventNamemétodo, em seguida, dispara o evento.

Dica

O protegido OnEventNamemétodo também permite que classes derivadas substituir o evento sem anexar um representante a ela.Uma classe derivada sempre deve chamar o OnEventNamemétodo da classe base para garantir que os delegados registrados receberão o evento.

O exemplo a seguir define o OnAlarmEvent método, que é responsável por gerar o AlarmEvent evento.

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);
   }

O exemplo a seguir define um método denominado Set que contém a lógica para acionar o evento chamando o OnAlarmEvent método. Se as horas e os minutos da hora do alarme igual as horas e minutos da hora atual, o Set método percorre uma AlarmEventArgs de objetos e fornece-o com a hora em que o alarme estava desativado. Após a execução de manipuladores de eventos, ele verifica o valor da Snooze propriedade. Se Snooze é false, mais nenhum evento de alarme está a ser gerado, assim, a Set método pode finalizar. Se Snooze é true, o alarme é desativado é incrementada pelo valor do tempo de Interval propriedade.

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);
}

O exemplo a seguir inclui todo o código de origem para a classe de alarme.

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);
   }
};

Consulte também

Tarefas

Como: gerar e consumir eventos

Como: implementar eventos em sua classe

Conceitos

Delegados e eventos

Outros recursos

Tratamento e disparada de eventos