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á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á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ě