Visão geral dos eventos em anexo
Extensible Application Markup Language (XAML) define um componente de linguagem e um tipo de evento chamado evento anexado. O conceito de um evento anexado permite que você adicione um manipulador para um evento específico a um elemento arbitrário em vez de a um elemento que realmente define ou herda o evento. Nesse caso, nem o objeto potencialmente gerando o evento nem a instância de manipulação de destino define ou de outra forma "possui" o evento.
Pré-requisitos
Este tópico pressupõe que você tenha lido Visão geral de eventos roteados e XAML no WPF.
Sintaxe do evento anexado
Os eventos anexados têm uma sintaxe XAML e um padrão de codificação que deve ser usado pelo código de suporte para dar suporte ao uso de eventos anexados.
Na sintaxe XAML, o evento anexado é especificado não apenas pelo nome do evento, mas pelo tipo próprio mais o nome do evento, separados por um ponto (.). Como o nome do evento é qualificado com o nome do tipo a que pertence, a sintaxe do evento anexado permite que ele seja aplicado a qualquer elemento que possa ser instanciado.
Por exemplo, a sintaxe do XAML a seguir serve para anexar um manipulador para um evento personalizado NeedsCleaning
associado.
<aqua:Aquarium Name="theAquarium" Height="600" Width="800" aqua:AquariumFilter.NeedsCleaning="WashMe"/>
Observe o prefixo aqua:
; O prefixo é necessário neste caso porque o evento anexado é um evento personalizado que vem de um XMLNs mapeado personalizado.
Como o WPF implementa eventos anexados
No WPF, os eventos anexados são apoiados por um campo RoutedEvent e são encaminhados através da hierarquia depois de serem desencadeados. Normalmente, a origem do evento anexado (o objeto que gera o evento) é uma fonte de sistema ou serviço, e o objeto que executa o código que gera o evento não é, portanto, uma parte direta da árvore de elementos.
Cenários para eventos anexados
No WPF, os eventos anexados estão presentes em determinadas áreas de recursos onde há abstração de nível de serviço, como para os eventos habilitados pela classe Mouse estática ou pela classe Validation. As classes que interagem ou usam o serviço podem usar o evento na sintaxe de evento anexado ou podem optar por exibir o evento anexado como um evento roteado que faz parte de como a classe integra os recursos do serviço.
Embora o WPF defina vários eventos anexados, os cenários em que você usará ou manipulará o evento anexado diretamente são muito limitados. Geralmente, o evento anexado cumpre uma função de arquitetura, mas é então encaminhado para um evento roteado não anexado, suportado por um "wrapper" de evento CLR.
Por exemplo, o evento anexado subjacente Mouse.MouseDown pode ser tratado mais facilmente num UIElement utilizando o MouseDown nesse contexto UIElement, ao invés de lidar com a complexidade da sintaxe de eventos anexados, seja em XAML ou código. O evento anexado serve um propósito na arquitetura porque permite a expansão futura de dispositivos de entrada. O dispositivo hipotético só precisaria levantar Mouse.MouseDown para simular a entrada do mouse, e não precisaria derivar de Mouse para fazê-lo. No entanto, esse cenário envolve a manipulação de código dos eventos, e a manipulação XAML do evento anexado não é relevante para esse cenário.
Gerenciando um evento anexado no WPF
O processo para manipular um evento anexado e o código do manipulador que irá escrever é basicamente o mesmo que para um evento encaminhado.
Em geral, um evento anexado do WPF não é muito diferente de um evento roteado do WPF. As diferenças são como o evento é originado e como ele é exposto por uma classe como membro (o que também afeta a sintaxe do manipulador XAML).
No entanto, como observado anteriormente, os eventos anexados existentes do WPF não são especificamente destinados ao tratamento no WPF. Mais frequentemente, o objetivo do evento é permitir que um elemento composto relate um estado para um elemento pai na composição, caso em que o evento geralmente é gerado no código e também depende do tratamento de classe na classe pai relevante. Por exemplo, espera-se que os itens dentro de um Selector gerem o evento Selected anexado, que é então manipulado pela classe Selector e, em seguida, potencialmente convertido pela classe Selector num evento roteado diferente, SelectionChanged. Para obter mais informações sobre eventos roteados e manipulação de classe, consulte Marcando eventos roteados como manipulados e Manipulação de classe.
Definindo seus próprios eventos anexados como eventos roteados
Se você estiver derivando de classes base comuns do WPF, poderá implementar seus próprios eventos anexados incluindo certos métodos de padrão em sua classe e usando métodos de utilitário que já estão presentes nas classes base.
O padrão é o seguinte:
Um método AddEventNameHandler com dois parâmetros. O primeiro parâmetro é a instância à qual o manipulador de eventos é adicionado. O segundo parâmetro é o manipulador de eventos a ser adicionado. O método deve ser
public
estatic
, sem valor de retorno.Um método RemoveEventNameHandler com dois parâmetros. O primeiro parâmetro é a instância da qual o manipulador de eventos é removido. O segundo parâmetro é o manipulador de eventos a ser removido. O método deve ser
public
estatic
, sem valor de retorno.
O método acessador AddEventNameHandler facilita o processamento XAML quando os atributos do manipulador de eventos anexado são declarados num elemento. Os métodos AddEventNameHandler e RemoveEventNameHandler também permitem o acesso de código ao repositório do manipulador de eventos para o evento anexado.
Esse padrão geral ainda não é preciso o suficiente para implementação prática em uma estrutura, porque qualquer implementação de leitor XAML pode ter esquemas diferentes para identificar eventos subjacentes na linguagem e arquitetura de suporte. Esta é uma das razões pelas quais o WPF implementa eventos anexados como eventos roteados; o identificador a ser usado para um evento (RoutedEvent) já está definido pelo sistema de eventos WPF. Além disso, o encaminhamento de um evento é uma extensão natural da implementação no conceito de evento anexado no nível da linguagem XAML.
A implementação AddEventNameHandler para um evento anexado do WPF consiste em chamar o AddHandler com o evento encaminhado e o handler como argumentos.
Essa estratégia de implementação e o sistema de eventos direcionados, em geral, limitam a manipulação dos eventos anexados a classes derivadas de UIElement ou a classes derivadas de ContentElement, uma vez que apenas essas classes têm implementações de AddHandler.
Por exemplo, o código a seguir define o evento anexado NeedsCleaning
na classe proprietária Aquarium
, usando a estratégia de eventos anexados do WPF para declarar o evento como um evento encaminhado.
public static readonly RoutedEvent NeedsCleaningEvent = EventManager.RegisterRoutedEvent("NeedsCleaning", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AquariumFilter));
public static void AddNeedsCleaningHandler(DependencyObject d, RoutedEventHandler handler)
{
UIElement uie = d as UIElement;
if (uie != null)
{
uie.AddHandler(AquariumFilter.NeedsCleaningEvent, handler);
}
}
public static void RemoveNeedsCleaningHandler(DependencyObject d, RoutedEventHandler handler)
{
UIElement uie = d as UIElement;
if (uie != null)
{
uie.RemoveHandler(AquariumFilter.NeedsCleaningEvent, handler);
}
}
Public Shared ReadOnly NeedsCleaningEvent As RoutedEvent = EventManager.RegisterRoutedEvent("NeedsCleaning", RoutingStrategy.Bubble, GetType(RoutedEventHandler), GetType(AquariumFilter))
Public Shared Sub AddNeedsCleaningHandler(ByVal d As DependencyObject, ByVal handler As RoutedEventHandler)
Dim uie As UIElement = TryCast(d, UIElement)
If uie IsNot Nothing Then
uie.AddHandler(AquariumFilter.NeedsCleaningEvent, handler)
End If
End Sub
Public Shared Sub RemoveNeedsCleaningHandler(ByVal d As DependencyObject, ByVal handler As RoutedEventHandler)
Dim uie As UIElement = TryCast(d, UIElement)
If uie IsNot Nothing Then
uie.RemoveHandler(AquariumFilter.NeedsCleaningEvent, handler)
End If
End Sub
Observe que o método usado para estabelecer o campo de identificador de evento anexado, RegisterRoutedEvent, é, na verdade, o mesmo método usado para registrar um evento roteado não anexado. Os eventos anexados e os eventos roteados são registrados em um armazenamento interno centralizado. Esta implementação da loja de eventos permite a perceção conceptual de "eventos como uma interface", que é discutida na secção Visão Geral de Eventos Roteados.
Gerando um evento anexado do WPF
Normalmente, você não precisa gerar eventos anexados definidos pelo WPF existentes a partir do seu código. Esses eventos seguem o modelo conceitual geral de "serviço", e classes de serviço como InputManager são responsáveis por gerar os eventos.
No entanto, se você estiver definindo um evento anexado personalizado com base no modelo WPF de basear eventos anexados em RoutedEvent, você pode usar RaiseEvent para gerar um evento anexado de qualquer UIElement ou ContentElement. Levantar um evento roteado (anexado ou não) requer que se declare um elemento específico na árvore de elementos como a origem do evento; essa origem é identificada como o chamador RaiseEvent. É da responsabilidade do seu serviço determinar qual elemento é relatado como fonte na árvore.
Ver também
.NET Desktop feedback