Visão geral de eventos anexados

A linguagem XAML (Extensible Application Markup Language) 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 um elemento que realmente define ou herda o evento. Nesse caso, nem o objeto potencialmente aumentando o evento, nem a instância de tratamento define ou caso contrário, é "proprietário" do evento.

Pré-requisitos

Este tópico pressupõe que você tenha lido Visão geral de eventos roteados e XAML no WPF.

Sintaxe de 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 do evento anexado.

Na sintaxe XAML, o evento anexado é especificado não apenas por seu nome de evento, mas por seu tipo de propriedade mais o nome do evento, separados por um ponto (.). Porque o nome do evento é qualificado com o nome do seu tipo proprietário, a sintaxe de evento anexado permite que qualquer evento anexado a ser anexado a qualquer elemento que pode ser instanciado.

Por exemplo, a sintaxe XAML a seguir está para anexar um manipulador para um evento anexado personalizado NeedsCleaning :

<aqua:Aquarium Name="theAquarium" Height="600" Width="800" aqua:AquariumFilter.NeedsCleaning="WashMe"/>

Observe o aqua: prefixo; o prefixo é necessário nesse caso porque o evento anexado é um evento personalizado proveniente de um xmlns personalizado e mapeado.

Como o WPF implementa eventos anexados

No WPF, os eventos anexados são apoiados por um RoutedEvent campo e são roteados pela árvore depois de serem gerados. 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 estática Mouse ou pela Validation classe. Classes que interagem com ou usam o serviço podem usar o evento na sintaxe de evento anexado ou eles podem escolher aumentar o evento anexado como um evento roteado que faz parte de como a classe integra os recursos do serviço.

Embora o WPF defina um número de eventos anexados, os cenários em que você usará ou manipulará o evento anexado diretamente são muito limitados. Geralmente, o evento anexado serve a uma finalidade de arquitetura, mas é encaminhado para um evento roteado não anexado (apoiado com um evento CLR "wrapper").

Por exemplo, o evento anexado subjacente pode ser manipulado mais facilmente em qualquer dado UIElement usando MouseDown nele UIElement em vez de lidar com a sintaxe de evento Mouse.MouseDown anexado em XAML ou código. O evento anexado serve um propósito na arquitetura porque permite expansão futura de dispositivos de entrada. O dispositivo hipotético só precisaria aumentar 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.

Tratando um evento anexado no WPF

O processo para identificar um evento anexado e o código do manipulador que você vai escrever, é basicamente o mesmo para um evento roteado.

Em geral, um evento anexado WPF não é muito diferente de um evento roteado 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 do WPF existentes não se destinam especificamente ao tratamento no WPF. Com mais frequência, o objetivo do evento é habilitar um elemento de composição para relatar um estado para um elemento pai na composição, no qual, o evento é gerado normalmente em código e também depende do tratamento da classe na classe pai relevante. Por exemplo, espera-se que os itens dentro de um gerem o evento anexadoSelected, que é então a classe manipulada Selector pela classe e, em seguida, potencialmente convertida pela Selector classe em um Selector evento roteado diferente, SelectionChanged. Para obter mais informações sobre eventos roteados e identificação por classe, consulte Marcando eventos roteados como manipulados e tratamento de classes.

Definir seus próprios eventos anexados como eventos roteados

Se você estiver derivando de classes base WPF comuns, você pode implementar seus próprios eventos anexados incluindo determinados 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 e static, 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 e static, sem valor de retorno.

O método acessador AddEventNameHandler facilita o processamento XAML quando atributos de manipulador de eventos anexados são declarados em um elemento. Os métodos AddEventName Handler e RemoveEventNameHandler também habilitam 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 específica pode ter esquemas diferentes para identificar eventos subjacentes na linguagem e arquitetura de suporte. Essa é 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 roteamento de um evento é uma extensão de implementação natural no conceito de nível de linguagem XAML de um evento anexado.

A implementação AddEventNameHandler para um evento anexado WPF consiste em chamar o com o evento roteado e o AddHandler manipulador como argumentos.

Essa estratégia de implementação e o sistema de eventos roteados em geral restringem o tratamento de eventos anexados a UIElement classes derivadas ou ContentElement classes derivadas, porque somente essas classes têm AddHandler implementações.

Por exemplo, o código a seguir define o evento anexado na classe Aquariumproprietária, usando a estratégia de evento anexado WPF de declarar o evento anexado NeedsCleaning como um evento roteado.

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 identificador de evento anexado, , RegisterRoutedEventé na verdade o mesmo método usado para registrar um evento roteado não anexado. Eventos anexados e eventos roteados são registrados para um repositório centralizado interno. Essa implementação de repositório de eventos permite a consideração conceitual de "eventos como uma interface" que é abordada na visão geral de eventos roteados.

Gerar um evento anexado 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 no RoutedEvent, poderá usar RaiseEvent para gerar um evento anexado de qualquer UIElement ou ContentElement. A geração de um evento roteado (anexado ou não) requer que você declare um elemento específico na árvore de elementos como a origem do evento; essa fonte é relatada como o RaiseEvent interlocutor. Determinar qual elemento é relatado como a fonte na árvore é responsabilidade do serviço

Confira também