Manipulando e acionando eventosHandling and raising events

Os eventos no .NET são baseados no modelo de representante.Events in .NET are based on the delegate model. O modelo de representante segue o padrão de design do observador, que permite a um assinante se registrar em um provedor e receber notificações dele.The delegate model follows the observer design pattern, which enables a subscriber to register with and receive notifications from a provider. Um remetente de eventos envia uma notificação por push de que um evento ocorreu e um receptor de eventos recebe essa notificação e define uma resposta.An event sender pushes a notification that an event has happened, and an event receiver receives that notification and defines a response to it. Este artigo descreve os principais componentes do modelo de representante, como consumir eventos em aplicativos e como implementar eventos no código.This article describes the major components of the delegate model, how to consume events in applications, and how to implement events in your code.

Para saber mais sobre como manipular eventos em aplicativos da Windows 8.x Store, confira Visão geral de eventos e eventos roteados.For information about handling events in Windows 8.x Store apps, see Events and routed events overview.

EventosEvents

Um evento é uma mensagem enviada por um objeto para sinalizar a ocorrência de uma ação.An event is a message sent by an object to signal the occurrence of an action. A ação pode ser causada pela interação do usuário, como o clique em um botão, ou ser resultado de alguma outra lógica de programa, como a alteração do valor de uma propriedade.The action can be caused by user interaction, such as a button click, or it can result from some other program logic, such as changing a property’s value. O objeto que aciona o evento é chamado de remetente do evento.The object that raises the event is called the event sender. O remetente do evento não sabe qual objeto ou método receberá (identificador) os eventos que ele aciona.The event sender doesn't know which object or method will receive (handle) the events it raises. O evento normalmente é membro do remetente do evento. Por exemplo, o evento Click é membro da classe Button e o evento PropertyChanged é membro da classe que implementa a interface INotifyPropertyChanged.The event is typically a member of the event sender; for example, the Click event is a member of the Button class, and the PropertyChanged event is a member of the class that implements the INotifyPropertyChanged interface.

Para definir um evento, use a palavra-chave event no C# ou Event no Visual Basic na assinatura da sua classe de evento e especifique o tipo de representante para o evento.To define an event, you use the C# event or the Visual Basic Event keyword in the signature of your event class, and specify the type of delegate for the event. Os representantes são descritos na próxima seção.Delegates are described in the next section.

Normalmente, para acionar um evento, você adiciona um método que é marcado como protected e virtual (em C#) ou Protected e Overridable (no Visual Basic).Typically, to raise an event, you add a method that is marked as protected and virtual (in C#) or Protected and Overridable (in Visual Basic). Dê a esse método o nome OnEventName; por exemplo, OnDataReceived.Name this method OnEventName; for example, OnDataReceived. O método deve usar um parâmetro que especifica um objeto de dados de evento, que é um objeto do tipo EventArgs ou um tipo derivado.The method should take one parameter that specifies an event data object, which is an object of type EventArgs or a derived type. Você fornece esse método para permitir que as classes derivadas substituam a lógica para acionamento do evento.You provide this method to enable derived classes to override the logic for raising the event. Uma classe derivada sempre deve chamar o método OnEventName da classe base a fim de garantir que os representantes registrados recebam o evento.A derived class should always call the OnEventName method of the base class to ensure that registered delegates receive the event.

O exemplo de código a seguir mostra como declarar um evento denominado ThresholdReached.The following example shows how to declare an event named ThresholdReached. O evento está associado ao representante EventHandler e é gerado em um método chamado OnThresholdReached.The event is associated with the EventHandler delegate and raised in a method named 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

DelegadosDelegates

Um representante é um tipo que contém uma referência a um método.A delegate is a type that holds a reference to a method. Um representante é declarado com uma assinatura que mostra o tipo de retorno e os parâmetros para os métodos aos quais faz referência, e pode conter referências apenas aos métodos que correspondem à sua assinatura.A delegate is declared with a signature that shows the return type and parameters for the methods it references, and it can hold references only to methods that match its signature. Portanto, um representante é equivalente a um ponteiro de função fortemente tipado ou um retorno de chamada.A delegate is thus equivalent to a type-safe function pointer or a callback. Uma declaração de representante é suficiente para definir uma classe de representante.A delegate declaration is sufficient to define a delegate class.

Representantes têm muitos usos no .NET.Delegates have many uses in .NET. No contexto de eventos, um representante é um intermediário (ou mecanismo do tipo ponteiro) entre a origem do evento e o código que manipula o evento.In the context of events, a delegate is an intermediary (or pointer-like mechanism) between the event source and the code that handles the event. Associe um representante a um evento incluindo o tipo de representante na declaração do evento, como mostrado no exemplo da seção anterior.You associate a delegate with an event by including the delegate type in the event declaration, as shown in the example in the previous section. Para obter mais informações sobre representantes, consulte a classe Delegate.For more information about delegates, see the Delegate class.

O .NET fornece os representantes EventHandler e EventHandler<TEventArgs> para dar suporte à maioria dos cenários de evento..NET provides the EventHandler and EventHandler<TEventArgs> delegates to support most event scenarios. Use o representante EventHandler para todos os eventos que não incluem dados de evento.Use the EventHandler delegate for all events that do not include event data. Use o representante EventHandler<TEventArgs> para eventos que incluem dados sobre o evento.Use the EventHandler<TEventArgs> delegate for events that include data about the event. Esses representantes não têm valor de tipo de retorno e usam dois parâmetros (um objeto para a origem do evento e um objeto para dados do evento).These delegates have no return type value and take two parameters (an object for the source of the event, and an object for event data).

Os representantes são multicast, o que significa que eles podem manter referências a mais de um método de manipulação de eventos.Delegates are multicast, which means that they can hold references to more than one event-handling method. Para obter detalhes, consulte a página de referência Delegate.For details, see the Delegate reference page. Os representantes proporcionam flexibilidade e controle refinado na manipulação de eventos.Delegates provide flexibility and fine-grained control in event handling. Um representante atua como um dispatcher de evento para a classe que aciona o evento ao manter uma lista de manipuladores de eventos registrados para o evento.A delegate acts as an event dispatcher for the class that raises the event by maintaining a list of registered event handlers for the event.

Para cenários em que os representantes EventHandler e EventHandler<TEventArgs> não funcionam, você pode definir um representante.For scenarios where the EventHandler and EventHandler<TEventArgs> delegates do not work, you can define a delegate. Os cenários que exigem que você defina um representante são muito raros; por exemplo, quando você deve trabalhar com código que não reconhece genéricos.Scenarios that require you to define a delegate are very rare, such as when you must work with code that does not recognize generics. Marque um representante com a palavra-chave delegate no C# e Delegate no Visual Basic na declaração.You mark a delegate with the C# delegate and Visual Basic Delegate keyword in the declaration. O exemplo a seguir mostra como declarar um representante chamado ThresholdReachedEventHandler.The following example shows how to declare a delegate named ThresholdReachedEventHandler.

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

Dados de eventoEvent data

Os dados associados a um evento podem ser fornecidos por meio de uma classe de dados do evento.Data that is associated with an event can be provided through an event data class. O .NET fornece muitas classes de dados de evento que podem ser usadas em seus aplicativos..NET provides many event data classes that you can use in your applications. Por exemplo, a classe SerialDataReceivedEventArgs é a classe de dados de evento do evento SerialPort.DataReceived.For example, the SerialDataReceivedEventArgs class is the event data class for the SerialPort.DataReceived event. O .NET segue um padrão de nomenclatura de terminação para todas as classes de dados de evento com EventArgs..NET follows a naming pattern of ending all event data classes with EventArgs. Determine qual classe de dados de evento está associada a um evento observando o representante do evento.You determine which event data class is associated with an event by looking at the delegate for the event. Por exemplo, o representante SerialDataReceivedEventHandler inclui a classe SerialDataReceivedEventArgs como um de seus parâmetros.For example, the SerialDataReceivedEventHandler delegate includes the SerialDataReceivedEventArgs class as one of its parameters.

A classe EventArgs é o tipo base para todas as classes de dados de evento.The EventArgs class is the base type for all event data classes. EventArgs também é a classe usada quando um evento não tem nenhum dado associado.EventArgs is also the class you use when an event does not have any data associated with it. Quando você criar um evento cuja finalidade seja apenas notificar outras classes de que algo aconteceu e que não precise passar nenhum dado, inclua a classe EventArgs como o segundo parâmetro no representante.When you create an event that is only meant to notify other classes that something happened and does not need to pass any data, include the EventArgs class as the second parameter in the delegate. Você poderá passar o valor EventArgs.Empty quando nenhum dado for fornecido.You can pass the EventArgs.Empty value when no data is provided. O representante EventHandler inclui a classe EventArgs como um parâmetro.The EventHandler delegate includes the EventArgs class as a parameter.

Quando quiser criar uma classe de dados de evento personalizada, crie uma classe derivada de EventArgs e forneça todos os membros necessários para passar dados que estejam relacionados ao evento.When you want to create a customized event data class, create a class that derives from EventArgs, and then provide any members needed to pass data that is related to the event. Normalmente, você deve usar o mesmo padrão de nomenclatura do .NET e terminar o nome da classe de dados de evento com EventArgs.Typically, you should use the same naming pattern as .NET and end your event data class name with EventArgs.

O exemplo a seguir mostra uma classe de dados de evento chamada ThresholdReachedEventArgs.The following example shows an event data class named ThresholdReachedEventArgs. Ele contém propriedades que são específicas ao evento que está sendo acionado.It contains properties that are specific to the event being raised.

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

Manipuladores de eventosEvent handlers

Para responder a um evento, você pode definir um método de manipulador de eventos no receptor do evento.To respond to an event, you define an event handler method in the event receiver. Esse método deve corresponder à assinatura do representante para o evento que está sendo manipulado.This method must match the signature of the delegate for the event you are handling. No manipulador de eventos, execute as ações que são necessárias quando o evento é acionado, como coletar a entrada do usuário depois que ele clica em um botão.In the event handler, you perform the actions that are required when the event is raised, such as collecting user input after the user clicks a button. Para receber notificações de ocorrência de eventos, o método de manipulador de eventos deve estar inscrito no evento.To receive notifications when the event occurs, your event handler method must subscribe to the event.

O exemplo a seguir mostra um método de manipulador de eventos chamado c_ThresholdReached que corresponde à assinatura para o representante EventHandler.The following example shows an event handler method named c_ThresholdReached that matches the signature for the EventHandler delegate. O método está inscrito no evento ThresholdReached.The method subscribes to the ThresholdReached event.

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

Manipuladores de eventos estáticos e dinâmicosStatic and dynamic event handlers

O .NET permite que os assinantes se registrem para receber notificações de eventos de modo estático ou dinâmico..NET allows subscribers to register for event notifications either statically or dynamically. Os manipuladores de eventos estáticos permanecem em vigor por toda a vida da classe cujos eventos eles manipulam.Static event handlers are in effect for the entire life of the class whose events they handle. Os manipuladores de eventos dinâmicos são ativados e desativados explicitamente durante a execução do programa, geralmente em resposta a alguma lógica de programa condicional.Dynamic event handlers are explicitly activated and deactivated during program execution, usually in response to some conditional program logic. Por exemplo, eles podem ser usados se as notificações de eventos forem necessárias apenas sob determinadas condições, ou se um aplicativo fornecer vários manipuladores de eventos e as condições de tempo de execução definirem o apropriado para uso.For example, they can be used if event notifications are needed only under certain conditions or if an application provides multiple event handlers and run-time conditions define the appropriate one to use. O exemplo na seção anterior mostra como adicionar dinamicamente um manipulador de eventos.The example in the previous section shows how to dynamically add an event handler. Para obter mais informações, veja Eventos (no Visual Basic) e Eventos (em C#).For more information, see Events (in Visual Basic) and Events (in C#).

Acionando vários eventosRaising multiple events

Se sua classe acionar vários eventos, o compilador vai gerar um campo por instância de representante de evento.If your class raises multiple events, the compiler generates one field per event delegate instance. Se o número de eventos for grande, o custo de armazenamento de um campo por representante pode não ser aceitável.If the number of events is large, the storage cost of one field per delegate may not be acceptable. Para esses casos, o .NET fornece propriedades de evento que você pode usar com outra estrutura de dados de sua escolha para armazenar representantes de eventos.For those situations, .NET provides event properties that you can use with another data structure of your choice to store event delegates.

As propriedades de evento consistem em declarações de evento acompanhadas por acessadores de evento.Event properties consist of event declarations accompanied by event accessors. Os acessadores de evento são métodos que você define para adicionar ou remover instâncias de representante de evento da estrutura de dados de armazenamento.Event accessors are methods that you define to add or remove event delegate instances from the storage data structure. Observe que as propriedades de evento são mais lentas que os campos de evento, pois cada representante de evento deve ser recuperado para que possa ser invocado.Note that event properties are slower than event fields, because each event delegate must be retrieved before it can be invoked. A compensação está entre a memória e a velocidade.The trade-off is between memory and speed. Se sua classe define muitos eventos que raramente são acionados, você desejará implementar as propriedades de evento.If your class defines many events that are infrequently raised, you will want to implement event properties. Para saber mais, confira Como manipular vários eventos usando propriedades de evento.For more information, see How to: Handle Multiple Events Using Event Properties.

TítuloTitle DescriçãoDescription
Como acionar e consumir eventosHow to: Raise and Consume Events Contém exemplos de como acionar e consumir eventos.Contains examples of raising and consuming events.
Como manipular vários eventos usando propriedades de eventoHow to: Handle Multiple Events Using Event Properties Mostrar como usar propriedades de evento para manipular vários eventos.Shows how to use event properties to handle multiple events.
Padrão de design do observadorObserver Design Pattern Descreve o padrão de design que permite a um assinante se registrar em um provedor e receber notificações dele.Describes the design pattern that enables a subscriber to register with, and receive notifications from, a provider.
Como consumir eventos em um aplicativo Web FormsHow to: Consume Events in a Web Forms Application Mostra como manipular um evento acionado por um controle do Web Forms.Shows how to handle an event that is raised by a Web Forms control.

Consulte tambémSee also