Sdílet prostřednictvím


Vyvolání události

Pokud chcete, aby vaše třída vyvolala událost, musíte poskytnout následující prvky:

  • Třída, která poskytuje data události.

  • Delegát události.

  • Třída, která vyvolá událost.

Definování třídy pro poskytnutí dat události

Když je událost vyvolána, tak podle konvence v rozhraní .NET Framework, předá data události své obslužné rutině událostí. Data události jsou poskytnuta třídou System.EventArgs, nebo třídou, která je z ní odvozena.

Událost často nemá žádná vlastní data. Fakt, že událost byla vyvolána, poskytuje veškeré informace, které požaduje obslužná rutina události. V tomto případě může událost předat objekt EventArgs své obslužné rutině. Třída EventArgs má pouze jeden člen, Empty, který není zděděný z System.Object. Lze jej použít k vytvoření instance nové třídy EventArgs.

Pokud událost nemá vlastní data, pak může předat instanci třídy odvozenou z EventArgs obslužné rutině událostí. V závislosti na přesnosti dat předaných událostí oblužným rutinám, můžete použít existující třídu dat události v rozhraní .NET Framework. Například pokud vaše obslužná rutina událostí umožňuje zrušit akci přidruženou k události, můžete použít třídu CancelEventArgs.

Pokud je třeba zadat vlastní data do obslužné rutiny a existující třída není k dispozici, můžete definovat vlastní třídu dat události. Musí být odvozena z System.EventArgs. Podle úmluvy se tato třída nazývá EventNameEventArgs. Následující příklad ukazuje tuto třídu vlastní události dat. Definuje třídu s názvem AlarmEventArgs, která poskytuje dvě položky dat pro oblužné rutiny událostí: Vlastnost jen pro čtení Time, která označuje, kdy byl alarm vypnut a vlastnost Snooze, která označuje, zda by měl být alarm znovu vypnut po stanoveném intervalu nebo zda by měly být budoucí alarmy zrušeny.

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

Definování delegáta pro událost

Delegát události slouží k definování signatury události. Určitý delegát události obvykle odpovídá určité třídě dat události. Podle úmluvy mají události v rozhraní .NET Framework signaturu EventName(sender, e), kde sender je Object, který poskytuje odkaz na třídu nebo strukturu, která vyvolala událost, a e je objekt EventArgs, nebo je objekt odvozený z EventArgs, který poskytuje data události. Potom má definice delegáta obvykle tvar EventNameHandler(sender, e).

Používáte-li třídu dat události, která je již definovaná v knihovně tříd rozhraní .NET Framework, nebo v knihovně třetí strany, je pravděpodobné, že odpovídající delegát události je také definován v této knihovně. Například delegáta EventHandler lze použít společně s třídou EventArgs. Podobně delegáta CancelEventHandler lze použít společně s třídou CancelEventArgs.

Pokud definujete vlastní třídu dat události, můžete také definovat vlastního delegáta pro definování signatury události, nebo můžete použít obecného delegáta Action<T1, T2>.

Následující příklad definuje delegáta události s názvem 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);

Definování třídy pro vyvolání události

Třída, která vyvolá událost musí poskytovat deklaraci události a definovat metodu, která vyvolává událost. Kromě toho musí poskytovat nějakou logiku k vyvolání události ve vlastnosti třídy, nebo metody.

Člen události ve vaší třídě je možné definovat pomocí klíčového slova event v jazyce C#, nebo příkazem Event v jazyce Visual Basic. Když kompilátor narazí na deklaraci události ve vaší třídě, vytvoří soukromého člena, jako například:

private EventNameHandler eh = null;

Kompilátor vytvoří také dvě veřejné metody add_EventName a remove_EventName. Tyto metody jsou háky události, které umožňují delegátům kombinaci, nebo odebrání z delegáta události eh. Podrobnosti jsou pro programátora skryty.

PoznámkaPoznámka

V jiných jazycích než C# a Visual Basic 2005, kompilátor nesmí automaticky generovat žádný kód odpovídající členu události a pravděpodobně budete muset explicitně definovat háky událostí a soukromé pole delegáta.

Následující příklad deklaruje událost s názvem AlarmEvent. Je výňatkem z příkladu pro třídu s názvem Alarm, jejíž kompletní zdrojový kód je uveden níže. Všimněte si, že má signaturu delegáta AlarmEventHandler.

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

Pokud jste definovali implementaci události, musíte určit, kdy vyvolat událost. Událost vyvoláte voláním chráněné metody OnEventName ve třídě, která definovala událost nebo v odvozené třídě. Metoda OnEventName pak vyvolá událost.

PoznámkaPoznámka

Chráněná metoda OnEventName také umožňuje odvozeným třídám přepsat událost bez připojení delegáta k odvozeným třídám.Odvozená třída musí vždy volat metodu OnEventName základní třídy pro ujištění, že registrovaní delegáti obdrží událost.

Následující příklad definuje metodu OnAlarmEvent, která je zodpovědná za vyvolání události 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);
   }

Následující příklad definuje metodu s názvem Set, která obsahuje logiku pro vyvolání události voláním metody OnAlarmEvent. Pokud se hodiny a minuty času alarmu rovnají hodinám a minutám aktuálního času, pak metoda Set vytvoří instanci objektu AlarmEventArgs a poskytne jej s časem, kdy se alarm vypnul. Po spuštění obslužné rutiny události kontroluje hodnotu vlastnosti Snooze. Pokud Snooze je false, pak nejsou vyvolány žádné další události alarmu a metoda Set tedy může být ukončena. Pokud Snooze je true, pak je čas vypnutí alarmu navýšen o hodnotu vlastnosti 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);
}

Následující příklad zahrnuje všechny zdrojové kódy pro třídu 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);
   }
};

Viz také

Úkoly

Postupy: Vyvolat a zpracovávat události

Postupy: Implementovat události ve vaší třídě

Koncepty

Události a Delegáti

Další zdroje

Zpracování a vyvolávání událostí