Sdílet prostřednictvím


Řízení a vyvolání událostí

Události v .NET jsou založené na modelu delegáta. Model delegáta se řídí vzorem návrhu pozorovatele , který umožňuje odběrateli zaregistrovat se a přijímat oznámení od poskytovatele. Odesílatel události odešle oznámení, když dojde k události. Příjemce události definuje odpověď. Tento článek popisuje hlavní komponenty modelu delegáta, jak využívat události v aplikacích a jak implementovat události v kódu.

Vyvolání událostí s odesílatelem události

Událost je zpráva odeslaná objektem, který signaluje výskyt akce. Akce může být interakce uživatele, například stisknutí tlačítka, nebo může mít za následek jinou logiku programu, například změnu hodnoty vlastnosti. Objekt, který vyvolá událost, se nazývá odesílatele události. Odesílatel události nezná objekt nebo metodu, která přijímá (zpracovává) 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í.

K definování události použijete klíčové slovo event v jazyce C# nebo Event v jazyce Visual Basic v signatuře třídy událostí a určíte typ delegáta pro událost. Delegáti jsou popsáni v další části.

K vyvolání události obvykle přidáte metodu označenou jako protected a virtual (v jazyce C#) nebo Protected a Overridable (v jazyce Visual Basic). Zásady vytváření názvů pro metodu jsou On<EventName>, například OnDataReceived. Metoda by měla mít jeden parametr, který určuje datový objekt události, což je objekt typu EventArgs nebo odvozený typ. Tuto metodu zadáte tak, aby odvozené třídy přepsaly logiku pro vyvolání události. Odvozená třída by měla vždy zavolat metodu On<EventName> ze základní třídy, aby bylo zajištěno, že registrovaní delegáti obdrží událost.

Následující příklad ukazuje, jak deklarovat událost s názvem ThresholdReached. Událost je spojena s delegátem EventHandler a vyvolána v metodě pojmenované OnThresholdReached.

class Counter
{
    public event EventHandler ThresholdReached;

    protected virtual void OnThresholdReached(EventArgs e)
    {
        ThresholdReached?.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

Deklarace podpisů delegáta pro obslužné rutiny událostí

Delegát je typ, který obsahuje odkaz na metodu. Delegát je deklarován s podpisem, který zobrazuje návratový typ a parametry pro metody, na které odkazuje. Může obsahovat odkazy pouze na metody, které odpovídají jeho podpisu. Delegát je ekvivalentní ukazateli funkce bezpečného typu nebo zpětnému volání. Deklarace delegáta je dostatečná k definování třídy delegáta.

Delegáti mají v .NET mnoho použití. V kontextu událostí je delegát zprostředkujícím mechanismem mezi zdrojem události a kódem, který událost zpracovává, podobně jako ukazatel. Delegáta přidružíte k události zahrnutím typu delegáta do deklarace události, jak je znázorněno v příkladu v předchozí části. Další informace o delegátech najdete v třídě Delegate.

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

Delegáti jsou objekty třídy multicast, což znamená, že mohou obsahovat odkazy na více než jednu metodu pro zpracování událostí. Další informace najdete na Delegate referenční stránce. Delegáti poskytují flexibilitu a jemné řízení při zpracování událostí. Delegát funguje jako dispečer událostí pro třídu, která vyvolává událost, a to tím, že udržuje seznam registrovaných obslužných rutin pro danou událost.

K definování potřebného delegáta použijte typy EventHandler a EventHandler<TEventArgs> delegáta. Delegáta označíte typem delegate v [C#](../../csharp/language-reference/builtin-types/reference-types.md#the-delegate-type) nebo typem Delegate v deklaraci v jazyce Visual Basic. 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)

Práce s datovými třídami událostí

Data přidružená k události je možné poskytnout prostřednictvím datové třídy události. .NET poskytuje mnoho datových tříd událostí, které můžete použít ve svých aplikacích. Například třída SerialDataReceivedEventArgs je datová třída události pro událost SerialPort.DataReceived. .NET se řídí vzorem pojmenování, kde všechny třídy dat událostí končí příponou EventArgs. To, která datová třída události je přidružená k události, určíte tak, že se podíváte na delegáta události. Delegát SerialDataReceivedEventHandler například přijímá třídu SerialDataReceivedEventArgs jako parametr.

Třída EventArgs je obvykle základním typem datových tříd událostí. Tuto třídu použijete také v případě, že událost nemá přidružená žádná data. Když vytvoříte událost, která předplatitelům oznámí, že se něco stalo bez dalších dat, zahrňte třídu EventArgs jako druhý parametr delegáta. Hodnotu EventArgs.Empty můžete předat, pokud nejsou k dispozici žádná data. Delegát EventHandler obsahuje třídu EventArgs jako parametr.

Můžete vytvořit třídu, která je odvozena z třídy EventArgs, aby poskytla všechny členy potřebné k předání dat souvisejících s událostí. Obvykle byste měli použít stejný vzor pojmenování jako .NET a ukončit název datové třídy události s příponou EventArgs.

Následující příklad ukazuje datovou třídu události s názvem ThresholdReachedEventArgs, která obsahuje vlastnosti specifické pro událost, která je vyvolána:

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

Reagovat na události pomocí obslužných programů

Chcete-li zareagovat na událost, vytvoříte v příjemci události metodu pro obsluhu události. Tato metoda musí odpovídat podpisu delegáta pro událost, kterou zpracováváte. V obslužné rutině události provedete akce, které jsou vyžadovány při vyvolání události, například shromažďování uživatelského vstupu po stisknutí tlačítka. Pokud chcete dostávat oznámení, když dojde k události, musí se vaše metoda obslužné rutiny události přihlásit k odběru události.

Následující příklad ukazuje metodu obslužné rutiny události, která se jmenuje c_ThresholdReached a odpovídá podpisu delegáta EventHandler. Metoda se přihlásí k odběru události ThresholdReached:

class ProgramTwo
{
    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

Použijte statické a dynamické obslužné rutiny událostí

.NET umožňuje odběratelům registrovat oznámení událostí staticky nebo dynamicky. Statické obslužné rutiny událostí jsou účinné během celé životnosti třídy, jejíž události zpracovávají. Dynamické obslužné rutiny událostí se explicitně aktivují a deaktivují během provádění programu, obvykle v reakci na určitou logiku podmíněného programu. Dynamické obslužné rutiny můžete použít, když jsou oznámení událostí potřebná pouze za určitých podmínek nebo když podmínky za běhu určují konkrétní obslužnou rutinu, která se má volat. Příklad v předchozí části ukazuje, jak dynamicky přidat zpracovatel událostí. Další informace najdete v tématu Události (v jazyce 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 instanci delegáta události. Pokud je počet událostí velký, náklady na úložiště jednoho pole pro každého delegáta nemusí být přijatelné. Pro tyto scénáře poskytuje .NET vlastnosti událostí, které můžete použít s jinou datovou strukturou podle vašeho výběru k ukládání delegátů událostí.

Vlastnosti události se skládají z deklarací událostí doprovázených přístupovými metodami události. Přístupové objekty událostí jsou metody, které definujete pro přidání nebo odebrání instancí delegátů událostí ze struktury dat úložiště.

Poznámka:

Vlastnosti událostí jsou pomalejší než událostní pole, protože každý delegát události musí být načten před vyvoláním.

Kompromis je mezi pamětí a rychlostí. Pokud vaše třída definuje mnoho událostí, které jsou zřídka vyvolány, měli byste implementovat vlastnosti události. Další informace naleznete v tématu Zpracování více událostí pomocí vlastností události.

Následující zdroje informací popisují další úlohy a koncepty související s prací s událostmi:

Revidovat referenci specifikace

Referenční dokumentace ke specifikaci je k dispozici pro rozhraní API, která podporují zpracování událostí:

Název rozhraní API Typ rozhraní API Odkazy
zpracovatel událostí Delegát EventHandler
Obslužné rutiny událostí<TEventArgs> Delegát EventHandler<TEventArgs>
EventArgs Třída EventArgs
Delegát Třída Delegate