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

Události v rozhraní .NET jsou založené na modelu delegáta. Model delegáta dodržuje vzor návrhu pozorovatele, který umožňuje předplatiteli zaregistrovat se a přijímat oznámení od poskytovatele. Odesílatel události vloží oznámení, že k události došlo, a příjemce události obdrží toto oznámení a definuje odpověď na ni. Tento článek popisuje hlavní komponenty modelu delegáta, způsob, jak spotřebovávat události v aplikacích a jak implementovat události v kódu.

Události

Událost je zpráva odeslaná objektem k signalizaci výskytu akce. Tato akce může být způsobena zásahem uživatele, například kliknutím na tlačítko, nebo může být výsledkem některé jiné logiky programu, jako je například změna hodnoty vlastnosti. Objekt, který vyvolává událost, se nazývá odesílatel události. Odesílatel události neví, který objekt nebo metoda obdrží (zpracuje) události, které vyvolá. Událost je obvykle členem odesílatele události; například Click událost je členem Button třídy a PropertyChanged událost je členem třídy, která implementuje INotifyPropertyChanged rozhraní.

chcete-li definovat událost, použijte event klíčové slovo C# nebo Visual Basic Event v signatuře třídy event a určete typ delegáta pro událost. Delegáti jsou popsáni v následující části.

Pro vyvolání události obvykle přidáte metodu, která je označena jako protected a virtual (v jazyce C#) nebo Protected a Overridable (v Visual Basic). Pojmenujte tuto metodu On EventName; například OnDataReceived . Metoda by měla přijmout jeden parametr, který určuje datový objekt události, což je objekt typu EventArgs nebo odvozený typ. Tuto metodu můžete zadat, chcete-li povolit odvozené třídy pro přepsání logiky pro vyvolání události. Odvozená třída by měla vždy volat On metodu EventName základní třídy, aby se zajistilo, že registrovaní delegáti obdrží událost.

Následující příklad ukazuje, jak deklarovat událost s názvem ThresholdReached . Událost je přidružena k EventHandler delegátovi a vyvolána v metodě s názvem OnThresholdReached .

class Counter
{
    public event EventHandler ThresholdReached;

    protected virtual void OnThresholdReached(EventArgs e)
    {
        EventHandler handler = ThresholdReached;
        handler?.Invoke(this, e);
    }

    // provide remaining implementation for the class
}
Public Class Counter
    Public Event ThresholdReached As EventHandler

    Protected Overridable Sub OnThresholdReached(e As EventArgs)
        RaiseEvent ThresholdReached(Me, e)
    End Sub

    ' provide remaining implementation for the class
End Class

Delegáti

Delegát je typ, který obsahuje odkaz na metodu. Delegát je deklarován s signaturou, která zobrazuje návratový typ a parametry pro metody, na které odkazuje, a může uchovávat odkazy pouze na metody, které odpovídají jejímu podpisu. Delegát je tedy ekvivalentní k ukazateli funkce bezpečnému pro typ nebo zpětnému volání. Deklarace delegáta postačuje k definování třídy delegáta.

Delegáti mají spoustu použití v .NET. V kontextu událostí delegát je zprostředkovatel (nebo mechanismus podobný ukazateli) mezi zdrojem události a kódem, který událost zpracovává. Delegáta můžete přidružit k události zahrnutím typu delegáta v deklaraci události, jak je znázorněno v příkladu v předchozí části. Další informace o delegátech naleznete v tématu Delegate Třída.

Rozhraní .NET poskytuje EventHandler EventHandler<TEventArgs> delegáty a pro podporu většiny scénářů událostí. Použijte EventHandler delegáta pro všechny události, které neobsahují data události. Použijte EventHandler<TEventArgs> delegáta pro události, které obsahují data o události. Tito Delegáti nemají žádnou hodnotu návratového typu a přebírají dva parametry (objekt pro zdroj události a objekt pro data události).

Delegáti jsou vícesměrové vysílání, což znamená, že mohou obsahovat odkazy na více než jednu metodu zpracování událostí. Podrobnosti najdete na Delegate referenční stránce. Delegáti poskytují flexibilitu a jemně odstupňovaný ovládací prvek pro zpracování událostí. Delegát funguje jako dispečer události pro třídu, která vyvolává událost tím, že udržuje seznam registrovaných obslužných rutin událostí pro událost.

U scénářů EventHandler , kde EventHandler<TEventArgs> Delegáti a nefungují, můžete definovat delegáta. Scénáře, které vyžadují, abyste definovali delegáta, jsou velmi vzácné, například když musíte pracovat s kódem, který nerozpozná obecné typy. označíte delegáta pomocí delegate Delegate klíčového slova C# a Visual Basic v deklaraci. Následující příklad ukazuje, jak deklarovat delegáta s názvem ThresholdReachedEventHandler .

public delegate void ThresholdReachedEventHandler(object sender, ThresholdReachedEventArgs e);
Public Delegate Sub ThresholdReachedEventHandler(sender As Object, e As ThresholdReachedEventArgs)

Data událostí

Data přidružená k události lze poskytnout prostřednictvím třídy dat události. Rozhraní .NET poskytuje mnoho datových tříd událostí, které můžete použít ve svých aplikacích. SerialDataReceivedEventArgsTřída je například třída dat události pro SerialPort.DataReceived událost. Rozhraní .NET se řídí vzorem pojmenování všech tříd dat událostí pomocí EventArgs . Určíte, která třída dat události je přidružena k události, a to tak, že se podíváte na delegáta události. Například SerialDataReceivedEventHandler delegát obsahuje SerialDataReceivedEventArgs třídu jako jeden z jeho parametrů.

EventArgsTřída je základní typ pro všechny třídy dat událostí. EventArgs je také třída, kterou použijete v případě, že k události nejsou přidružena žádná data. Když vytvoříte událost, která má pouze upozornit jiné třídy, k nimž došlo, a není nutné předávat žádná data, zahrňte EventArgs třídu jako druhý parametr delegáta. Hodnotu můžete předat, EventArgs.Empty Pokud nejsou k dispozici žádná data. EventHandlerDelegát obsahuje EventArgs třídu jako parametr.

Chcete-li vytvořit přizpůsobenou třídu dat události, vytvořte třídu, která je odvozena z EventArgs a poté poskytněte jakékoli členy potřebné k předání dat, která se vztahují k události. Obvykle byste měli použít stejný vzor pro pojmenování jako .NET a ukončit název třídy dat události pomocí EventArgs .

Následující příklad ukazuje třídu dat události s názvem ThresholdReachedEventArgs . Obsahuje vlastnosti, které jsou specifické pro vyvolání události.

public class ThresholdReachedEventArgs : EventArgs
{
    public int Threshold { get; set; }
    public DateTime TimeReached { get; set; }
}
Public Class ThresholdReachedEventArgs
    Inherits EventArgs

    Public Property Threshold As Integer
    Public Property TimeReached As DateTime
End Class

Obslužné rutiny událostí

Chcete-li reagovat na událost, definujte metodu obslužné rutiny události v přijímači událostí. Tato metoda se musí shodovat s signaturou delegáta události, kterou zpracováváte. V obslužné rutině události provedete akce, které jsou požadovány při vyvolání události, jako je například shromažďování uživatelského vstupu, poté, co uživatel klikne na tlačítko. Chcete-li dostávat oznámení, když dojde k události, metoda obslužné rutiny události musí být přihlášena k odběru události.

Následující příklad ukazuje metodu obslužné rutiny události s názvem c_ThresholdReached , která odpovídá signatuře EventHandler delegáta. Metoda se přihlašuje k odběru ThresholdReached události.

class Program
{
    static void Main()
    {
        var c = new Counter();
        c.ThresholdReached += c_ThresholdReached;

        // provide remaining implementation for the class
    }

    static void c_ThresholdReached(object sender, EventArgs e)
    {
        Console.WriteLine("The threshold was reached.");
    }
}
Module Module1

    Sub Main()
        Dim c As New Counter()
        AddHandler c.ThresholdReached, AddressOf c_ThresholdReached

        ' provide remaining implementation for the class
    End Sub

    Sub c_ThresholdReached(sender As Object, e As EventArgs)
        Console.WriteLine("The threshold was reached.")
    End Sub
End Module

Statické a dynamické obslužné rutiny událostí

.NET umožňuje předplatitelům registrovat se pro oznamování událostí staticky nebo dynamicky. Statické obslužné rutiny událostí jsou platné pro celou dobu života třídy, jejíž události zpracovávají. Dynamické obslužné rutiny událostí jsou explicitně aktivovány a dezaktivovány během provádění programu, obvykle v reakci na určitou logickou logiku programu. Můžete je například použít, pokud jsou oznámení o událostech nutná pouze za určitých podmínek nebo pokud aplikace poskytuje více obslužných rutin událostí a běhových podmínek definují příslušné rozhraní, které se má použít. Příklad v předchozím oddílu ukazuje, jak dynamicky přidat obslužnou rutinu události. další informace naleznete v tématu události (v Visual Basic) a události (v jazyce C#).

Vyvolání více událostí

Pokud vaše třída vyvolá více událostí, kompilátor vygeneruje jedno pole pro každou instanci delegáta události. Pokud je počet událostí velký, nemusí být náklady na úložiště jednoho pole na delegáta přijatelné. V těchto situacích poskytuje .NET vlastnosti události, které můžete použít s jinou datovou strukturou dle vašeho výběru k ukládání delegátů událostí.

Vlastnosti události se skládají z deklarací událostí spolu s přístupovými objekty událostí. Přístupové objekty událostí jsou metody, které definujete pro přidání nebo odebrání instancí delegátů událostí z datové struktury úložiště. Všimněte si, že vlastnosti události jsou pomalejší než pole události, protože každý delegát události musí být načten předtím, než může být vyvolán. Kompromis mezi pamětí a rychlostí. Pokud vaše třída definuje mnoho událostí, které jsou zřídka vyvolány, budete chtít implementovat vlastnosti události. Další informace najdete v tématu Postupy: zpracování více událostí pomocí vlastností události.

Nadpis Popis
Postupy: Vyvolávání a zpracovávání událostí Obsahuje příklady vyvolání a využívání událostí.
Postupy: Zpracování více událostí pomocí vlastností událostí Ukazuje, jak používat vlastnosti událostí pro zpracování více událostí.
Vzor návrhu pozorovatele Popisuje vzor návrhu, který umožňuje předplatiteli zaregistrovat se a přijímat oznámení od poskytovatele.

Viz také