Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Os programadores de aplicativos do WPF (Windows Presentation Foundation) e os autores de componentes podem usar eventos roteados para propagar eventos através de uma árvore de elementos e invocar manipuladores de eventos em vários escutadores na árvore. Esses recursos não são encontrados em eventos CLR (Common Language Runtime). Vários eventos do WPF são eventos roteados, como ButtonBase.Click. Este artigo discute os conceitos básicos de eventos roteados e oferece diretrizes sobre quando e como responder a eventos roteados.
Pré-requisitos
Este artigo pressupõe um conhecimento básico do CLR (Common Language Runtime), da programação orientada a objetos e de como o layout do elemento WPF pode ser conceituado como uma árvore. Para seguir os exemplos neste artigo, ele ajuda se você estiver familiarizado com XAML (Extensible Application Markup Language) e saber como escrever aplicativos WPF.
O que é um evento roteado?
Você pode considerar eventos roteados a partir de uma perspectiva funcional ou de implementação.
De uma perspectiva funcional, um evento roteado é um tipo de evento que pode invocar manipuladores em vários escutadores dentro de uma árvore de elementos e não apenas na origem do evento. Um ouvinte de eventos é o elemento em que um manipulador de eventos é anexado e invocado. Uma fonte de evento é o elemento ou objeto que originalmente gerou um evento.
De uma perspectiva de implementação , um evento roteado é um evento registrado com o sistema de eventos WPF, apoiado por uma instância da RoutedEvent classe e processado pelo sistema de eventos WPF. Normalmente, um evento roteado é implementado com um "envoltório" de evento CLR para habilitar a anexação de manipuladores em XAML e no código subjacente, como você faria com um evento CLR.
Os aplicativos WPF normalmente contêm muitos elementos, que foram declarados em XAML ou instanciados em código. Os elementos de um aplicativo existem dentro de sua árvore de elementos. Dependendo de como um evento roteado é definido, quando o evento é gerado em um elemento de origem, ele:
- Percorre a árvore de elementos do elemento de origem para o elemento raiz, que normalmente é uma página ou janela.
- Explora a árvore de elementos, começando pelo elemento raiz até o elemento de origem.
- Não percorre a árvore de elementos e ocorre apenas no elemento de origem.
Considere a seguinte árvore de elementos parciais:
<Border Height="30" Width="200" BorderBrush="Gray" BorderThickness="1">
<StackPanel Background="LightBlue" Orientation="Horizontal" Button.Click="YesNoCancelButton_Click">
<Button Name="YesButton">Yes</Button>
<Button Name="NoButton">No</Button>
<Button Name="CancelButton">Cancel</Button>
</StackPanel>
</Border>
A árvore de elementos é renderizada conforme mostrado:
Cada um dos três botões é uma fonte de evento em potencial Click . Quando um dos botões é clicado, ele aciona o Click
evento que se propaga do botão para o elemento raiz. Os elementos Button e Border não têm manipuladores de eventos anexados, mas o elemento StackPanel tem. Possivelmente outros elementos mais altos na árvore que não são mostrados também têm Click
manipuladores de eventos anexados. Quando o Click
evento atinge o StackPanel
elemento, o sistema de eventos WPF invoca o YesNoCancelButton_Click
manipulador anexado a ele. A sequência do evento Click
no exemplo é: Button
->StackPanel
->Border
-> sucessivos elementos pai.
Observação
O elemento que originalmente gerou um evento roteado é identificado como nos RoutedEventArgs.Source parâmetros do manipulador de eventos. O ouvinte de eventos é o elemento em que o manipulador de eventos é anexado e invocado e é identificado como o remetente nos parâmetros do manipulador de eventos.
Cenários de alto nível para eventos roteados
Aqui estão alguns dos cenários que motivaram o conceito de evento roteado e distingue-o de um evento CLR típico:
Controlar a composição e o encapsulamento: vários controles no WPF têm um modelo de conteúdo avançado. Por exemplo, você pode colocar uma imagem dentro de uma Button, que efetivamente estende a árvore visual do botão. Porém, a imagem adicionada não deve interromper o comportamento de teste de ocorrência do botão, que precisa responder quando um usuário clica nos pixels da imagem.
Pontos de anexo de manipulador singular: você pode registrar um manipulador para o evento de cada botão, mas com eventos roteados, você pode anexar um único manipulador, conforme mostrado no exemplo XAML anterior. Isso permite que você altere a árvore de elementos sob o manipulador singular, como adicionar ou remover mais botões, sem precisar registrar o evento de
Click
cada botão. Quando oClick
evento é gerado, a lógica do manipulador pode determinar de onde o evento veio. O manipulador a seguir, especificado na árvore de elementos XAML mostrada anteriormente, contém essa lógica:private void YesNoCancelButton_Click(object sender, RoutedEventArgs e) { FrameworkElement sourceFrameworkElement = e.Source as FrameworkElement; switch (sourceFrameworkElement.Name) { case "YesButton": // YesButton logic. break; case "NoButton": // NoButton logic. break; case "CancelButton": // CancelButton logic. break; } e.Handled = true; }
Private Sub YesNoCancelButton_Click(sender As Object, e As RoutedEventArgs) Dim frameworkElementSource As FrameworkElement = TryCast(e.Source, FrameworkElement) Select Case frameworkElementSource.Name Case "YesButton" ' YesButton logic. Case "NoButton" ' NoButton logic. Case "CancelButton" ' CancelButton logic. End Select e.Handled = True End Sub
Manipulação de classe: eventos roteados dão suporte a um manipulador de eventos de classe que são definidos por você em uma classe. Os manipuladores de classe manipulam um evento antes de qualquer manipulador de instância para o mesmo evento em qualquer instância da classe.
Referenciando um evento sem reflexão: cada evento roteado cria um RoutedEvent identificador de campo para fornecer uma técnica de identificação de evento robusta que não exige reflexão estática ou em tempo de execução para identificar o evento.
Como os eventos roteados são implementados
Um evento roteado é um evento registrado com o sistema de eventos WPF, apoiado por uma instância da RoutedEvent classe e processado pelo sistema de eventos WPF. A RoutedEvent
instância, obtida do registro, normalmente é armazenada como um public static readonly
membro da classe que a registrou. Essa classe é referida como a classe "proprietária" do evento. Normalmente, um evento roteado implementa um "wrapper" de evento CLR de nome idêntico. O wrapper de eventos CLR contém add
e remove
acessores para habilitar a anexação de manipuladores no XAML e no code-behind por meio da sintaxe de evento específica da linguagem. Os acessadores add
e remove
substituem a implementação do CLR e chamam o evento roteado e os métodos AddHandler e RemoveHandler. O mecanismo de conexão e o backup de eventos roteados é conceitualmente semelhante a como uma propriedade de dependência é uma propriedade CLR que é apoiada pela DependencyProperty classe e registrada com o sistema de propriedades do WPF.
O exemplo a seguir registra o Tap
evento roteado, armazena a instância retornada RoutedEvent
e implementa um wrapper de eventos CLR.
// Register a custom routed event using the Bubble routing strategy.
public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
name: "Tap",
routingStrategy: RoutingStrategy.Bubble,
handlerType: typeof(RoutedEventHandler),
ownerType: typeof(CustomButton));
// Provide CLR accessors for adding and removing an event handler.
public event RoutedEventHandler Tap
{
add { AddHandler(TapEvent, value); }
remove { RemoveHandler(TapEvent, value); }
}
' Register a custom routed event using the Bubble routing strategy.
Public Shared ReadOnly TapEvent As RoutedEvent = EventManager.RegisterRoutedEvent(
name:="Tap",
routingStrategy:=RoutingStrategy.Bubble,
handlerType:=GetType(RoutedEventHandler),
ownerType:=GetType(CustomButton))
' Provide CLR accessors for adding and removing an event handler.
Public Custom Event Tap As RoutedEventHandler
AddHandler(value As RoutedEventHandler)
[AddHandler](TapEvent, value)
End AddHandler
RemoveHandler(value As RoutedEventHandler)
[RemoveHandler](TapEvent, value)
End RemoveHandler
RaiseEvent(sender As Object, e As RoutedEventArgs)
[RaiseEvent](e)
End RaiseEvent
End Event
Estratégias de roteamento
Os eventos roteados utilizam uma das três estratégias de roteamento.
Borbulhando: inicialmente, os manipuladores de eventos na origem do evento são invocados. O evento roteado, em seguida, roteia para elementos pai sucessivos, invocando seus manipuladores de eventos, um a um, até alcançar a raiz da árvore de elementos. A maioria dos eventos roteados usa a estratégia de propagação por borbulhamento. ** Eventos roteados por propagação geralmente são usados para indicar alterações de entrada ou estado de controles compostos ou outros elementos da interface do usuário.
Tunelamento: inicialmente, os manipuladores de eventos na raiz da árvore de elementos são invocados. O evento roteado então passa por elementos filho sucessivos, acionando os manipuladores de eventos até chegar à fonte do evento. Os eventos que seguem uma rota de túnel também são conhecidos como eventos Preview. Os eventos de entrada do WPF geralmente são implementados como uma visualização e pares de bolhas.
Direto: somente manipuladores de eventos na origem do evento são invocados. Essa estratégia de não roteamento é análoga aos eventos da estrutura de interface do usuário do Windows Forms, que são eventos CLR padrão. Ao contrário dos eventos CLR, os eventos roteados diretos dão suporte à manipulação de classes e podem ser usados por EventSetters e EventTriggers.
Por que usar eventos roteados?
Como desenvolvedor de aplicativos, nem sempre você precisa saber ou se importar que o evento que você está tratando seja implementado como um evento roteado. Eventos roteados têm um comportamento especial, mas esse comportamento é praticamente invisível se você estiver lidando com um evento no elemento que o desencadeou. No entanto, os eventos roteados são relevantes quando você deseja anexar um manipulador de eventos a um elemento pai para tratar eventos gerados por elementos filhos, como dentro de um controle composto.
Os ouvintes de eventos roteados não precisam que os eventos roteados que eles manipulam sejam membros de sua classe. Qualquer UIElement ou ContentElement pode ser um ouvinte de eventos para qualquer evento roteado. Como elementos visuais derivam de UIElement
ou ContentElement
, você pode usar eventos roteados como uma "interface" conceitual que facilita a troca de informações de eventos entre diferentes elementos em um aplicativo. O conceito de "interface" para eventos roteados é particularmente aplicável a eventos de entrada.
Os eventos roteados oferecem suporte à troca de informações entre elementos ao longo da rota do evento, pois cada ouvinte tem acesso à mesma instância dos dados do evento. Se um elemento alterar algo nos dados do evento, essa alteração ficará visível para os elementos subsequentes na rota do evento.
Além do aspecto de roteamento, você pode optar por implementar um evento roteado em vez de um evento CLR padrão por estes motivos:
Alguns recursos de estilo e modelagem do WPF, como EventSetters e EventTriggers, exigem que o evento referenciado seja um evento roteado.
Os eventos roteados dão suporte a manipuladores de eventos de classe que manipulam um evento antes de qualquer manipulador de instância do mesmo evento em qualquer instância da classe ouvinte. Esse recurso é útil no design de controle porque seu manipulador de classe pode impor comportamentos de classe controlados por eventos que não podem ser suprimidos acidentalmente por um manipulador de instância.
Anexar e implementar um manipulador de eventos roteado
No XAML, você anexa um manipulador de eventos a um elemento declarando o nome do evento como um atributo no elemento do ouvinte de eventos. O valor do atributo é o nome do método do manipulador. O método de manipulador deve ser implementado na classe parcial do código subjacente para a página de XAML. O escutador de eventos é o elemento ao qual o manipulador de eventos é ligado e acionado.
Para um evento que seja um membro (herdado ou não) da classe de ouvinte, você pode anexar um manipulador da seguinte maneira:
<Button Name="Button1" Click="Button_Click">Click me</Button>
Se o evento não for um membro da classe do ouvinte, você deve usar o nome do evento especificado na forma de <owner type>.<event name>
. Por exemplo, como a classe StackPanel não implementa o evento Click, para anexar um manipulador a um StackPanel
para um evento Click
que propaga até esse elemento, você precisará usar a sintaxe de nome de evento qualificado:
<StackPanel Name="StackPanel1" Button.Click="Button_Click">
<Button>Click me</Button>
</StackPanel>
A assinatura do método do manipulador de eventos no code-behind deve corresponder ao tipo delegado para o evento roteado. O sender
parâmetro do RoutedEventHandler delegado para o Click evento especifica o elemento ao qual o manipulador de eventos está anexado. O args
parâmetro do RoutedEventHandler
delegado contém os dados do evento. Uma implementação de código de fundo compatível para o Button_Click
manipulador de eventos pode ser:
private void Button_Click(object sender, RoutedEventArgs e)
{
// Click event logic.
}
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
' Click event logic.
End Sub
Embora seja RoutedEventHandler o representante básico do manipulador de eventos roteado, alguns controles ou cenários de implementação exigem delegados diferentes que dão suporte a dados de eventos mais especializados. Por exemplo, para o evento roteado DragEnter, seu manipulador deve implementar o delegado DragEventHandler. Ao fazer isso, o código do manipulador pode acessar a propriedade DragEventArgs.Data nos dados do evento, que contém a carga útil da área de transferência da operação de arrastar.
A sintaxe XAML para adicionar manipuladores de eventos roteados é igual à dos manipuladores de eventos CLR padrão. Para obter mais informações sobre como adicionar manipuladores de eventos em XAML, consulte XAML no WPF. Para obter um exemplo completo de como anexar um manipulador de eventos a um elemento usando XAML, consulte Como lidar com um evento roteado
Para anexar um manipulador de eventos para um evento roteado a um elemento usando código, você geralmente tem duas opções:
Chame o método AddHandler diretamente. Manipuladores de eventos roteados sempre podem ser anexados dessa maneira. Este exemplo anexa um
Click
manipulador de eventos a um botão usando oAddHandler
método:Button1.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(Button_Click));
Button1.[AddHandler](ButtonBase.ClickEvent, New RoutedEventHandler(AddressOf Button_Click))
Para anexar um manipulador ao evento do botão
Click
a um elemento diferente na rota do evento, como um StackPanel chamadoStackPanel1
:StackPanel1.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(Button_Click));
StackPanel1.[AddHandler](ButtonBase.ClickEvent, New RoutedEventHandler(AddressOf Button_Click))
Caso o evento roteado implemente um empacotador de eventos CLR, utilize a sintaxe de evento específica do idioma para adicionar manipuladores de eventos da mesma forma que faria para um evento CLR padrão. A maioria dos eventos roteados do WPF existentes implementa o wrapper CLR, permitindo assim a sintaxe de evento específica da linguagem. Este exemplo anexa um
Click
manipulador de eventos a um botão usando a sintaxe específica do idioma:Button1.Click += Button_Click;
AddHandler Button1.Click, AddressOf Button_Click
Para obter um exemplo de como anexar um manipulador de eventos no código, consulte Como adicionar um manipulador de eventos usando código. Se você estiver codificando no Visual Basic, também poderá usar a Handles
palavra-chave para adicionar manipuladores como parte das declarações do manipulador. Para obter mais informações, consulte Manipulação de eventos do Visual Basic e do WPF.
O conceito de manipulado
Todos os eventos roteados compartilham uma classe base comum para dados de evento, que é a classe RoutedEventArgs. A RoutedEventArgs
classe define a propriedade booliana Handled . A finalidade da propriedade Handled
é permitir que qualquer manipulador de eventos ao longo da rota marque o evento roteado como manipulado. Para marcar um evento como manipulado, defina o valor de Handled
como true
no código do manipulador de eventos.
O valor de Handled
afeta como um evento roteado é processado enquanto percorre a rota do evento. Se Handled
estiver true
nos dados de eventos compartilhados de um evento roteado, os manipuladores anexados a outros elementos ao longo da rota de evento normalmente não serão invocados para essa instância de evento específica. Para a maioria dos cenários comuns do manipulador, marcar um evento como tratado efetivamente impede que manipuladores subsequentes ao longo da rota de evento, sejam manipuladores de instância ou de classe, respondam a essa instância de evento específica. No entanto, em casos raros em que você precisa que seu manipulador de eventos responda a eventos roteados que foram marcados como manipulados, você pode:
Vincule o manipulador no code-behind usando a sobrecarga de AddHandler(RoutedEvent, Delegate, Boolean) e definindo o parâmetro
handledEventsToo
comotrue
.Defina o HandledEventsToo atributo em um
EventSetter
paratrue
.
O conceito de Handled
pode afetar a forma como você projeta seu aplicativo e codifica seus manipuladores de eventos. Você pode conceituar Handled
como um protocolo simples para processamento de eventos roteados. A maneira como você usa esse protocolo cabe a você, mas o uso esperado do Handled
parâmetro é:
Se um evento roteado for marcado como manipulado, ele não precisará ser tratado novamente por outros elementos ao longo da rota.
Se um evento roteado não está marcado como manipulado, os escutadores mais cedo na rota do evento não possuem um manipulador para o evento, ou nenhum dos manipuladores registrados respondeu ao evento de uma forma que justifique marcar o evento como manipulado. Os manipuladores no ouvinte atual têm três cursos de ação possíveis:
Não faça nenhuma ação. O evento permanece sem tratamento e é direcionado para o próximo ouvinte na árvore.
Execute o código em resposta ao evento, mas não a ponto de justificar a marcação do evento como tratado. O evento permanece sem tratamento e é direcionado para o próximo ouvinte na árvore.
Executar o código em resposta ao evento, em uma medida que justifique marcar o evento como tratado. Marque o evento como tratado nas informações do evento. O evento ainda se direciona para o próximo escutador na árvore, mas a maioria dos escutadores não acionam mais os manipuladores. A exceção são os ouvintes com manipuladores que foram especificamente registrados com
handledEventsToo
definido paratrue
.
Para obter mais informações sobre como lidar com eventos roteados, consulte Marcando eventos roteados como manipulados e manipulação de classe.
Embora os desenvolvedores que manipulam apenas um evento roteado borbulhante no objeto que o disparou possam não estar preocupados com outros escutadores, é uma boa prática marcar o evento como manipulado de qualquer maneira. Isso impede efeitos colaterais inesperados se um elemento mais adiante na rota de evento tiver um manipulador para o mesmo evento roteado.
Manipuladores de classe
Os manipuladores de eventos roteados podem ser manipuladores de instância ou de classe. Manipuladores de classe para uma determinada classe são invocados antes que qualquer manipulador de instância responda ao mesmo evento em qualquer instância dessa classe. Devido a esse comportamento, quando os eventos roteados são marcados como manipulados, eles geralmente são marcados dessa forma dentro de manipuladores de classe. Há dois tipos de manipuladores de classe:
- Manipuladores de eventos de classe estática, que são registrados chamando o RegisterClassHandler método dentro de um construtor de classe estática.
- Substitua manipuladores de eventos de classe, que são registrados substituindo métodos de evento virtual de classe base. Os métodos de evento virtual de classe base existem principalmente para eventos de entrada e têm nomes que começam com o nome< do evento On> e o nome< do evento OnPreview>.
Alguns dos controles do WPF têm tratamento de classe embutido para determinados eventos roteados. O tratamento de classe pode dar a aparência externa de que o evento roteado nunca é acionado, mas, na realidade, está sendo marcado como tratado por um manipulador de classe. Se você precisar que o manipulador de eventos responda ao evento manipulado, registre seu manipulador com handledEventsToo
definido como true
. Para obter mais informações, tanto sobre como implementar seus próprios gestores de classe ou contornar o tratamento indesejado de classes, consulte Marcando eventos roteados como tratados e manipulação de classe.
Eventos anexados no WPF
A linguagem XAML também define um tipo especial de evento chamado evento anexado. Eventos anexados podem ser usados para definir um novo evento roteado em uma classe não-elemento e gerar esse evento em qualquer elemento em sua árvore. Para fazer isso, você deve registrar o evento anexado como um evento roteado e fornecer um código de backup específico que dê suporte à funcionalidade de evento anexado. Como os eventos anexados são registrados como eventos roteados, quando gerados em um elemento, eles se propagam pela árvore de elementos.
Na sintaxe XAML, um evento anexado é especificado pelo nome do evento e pelo tipo de proprietário, na forma de <owner type>.<event name>
. Como o nome do evento é qualificado pelo nome de seu tipo proprietário, a sintaxe permite que o evento seja anexado a qualquer elemento que possa ser instanciado. Essa sintaxe também é aplicável aos manipuladores de eventos roteados regulares que são anexados a um elemento arbitrário ao longo da rota do evento. Você também pode anexar manipuladores para eventos anexados no código por trás chamando o método AddHandler no objeto ao qual o manipulador deve ser anexado.
O sistema de entrada do WPF usa eventos anexados extensivamente. No entanto, quase todos esses eventos anexados são exibidos como eventos roteados não anexados equivalentes por meio de elementos base. Você raramente usará ou manipulará eventos anexados diretamente. Por exemplo, é mais fácil lidar com o evento anexado subjacente em um Mouse.MouseDown evento roteado UIElement equivalente UIElement.MouseDown do que usando a sintaxe de evento anexada em XAML ou code-behind.
Para obter mais informações sobre eventos anexados no WPF, consulte a visão geral de eventos anexados.
Nomes de eventos qualificados em XAML
A sintaxe <owner type>.<event name>
qualifica um nome de evento com o nome do tipo ao qual ele pertence. Essa sintaxe permite que um evento seja anexado a qualquer elemento, não apenas aos elementos que implementam o evento como um membro de sua classe. A sintaxe é aplicável ao anexar manipuladores em XAML para eventos anexados ou eventos roteados em elementos arbitrários ao longo da rota do evento. Considere o cenário em que você deseja anexar um manipulador a um elemento pai para lidar com eventos roteados gerados em elementos filhos. Se o elemento pai não tiver o evento roteado como membro, você precisará usar a sintaxe de nome de evento qualificado. Por exemplo:
<StackPanel Name="StackPanel1" Button.Click="Button_Click">
<Button>Click me</Button>
</StackPanel>
No exemplo, o listener do elemento pai ao qual o manipulador de eventos é adicionado é um StackPanel. No entanto, o evento roteado Click é implementado e acionado na classe ButtonBase, sendo disponibilizado para a classe Button por meio de herança. Embora a Button classe "possua" o Click
evento, o sistema de eventos roteados permite que os manipuladores de qualquer evento roteado sejam anexados a qualquer ouvinte UIElement ou instância de ouvinte ContentElement que, de outra forma, poderia ter manipuladores para um evento CLR. O namespace padrão xmlns
para esses nomes de atributo de evento qualificado normalmente é o namespace do WPF xmlns
padrão, mas você também pode especificar namespaces prefixados para eventos roteados personalizados. Para obter mais informações sobre xmlns
, consulte namespaces XAML e mapeamento de namespace para WPF XAML
Eventos de entrada do WPF
Uma aplicação frequente de eventos roteados na plataforma WPF é para eventos de entrada.
Os eventos de entrada do WPF que ocorrem em pares são implementados para que uma única ação do usuário de um dispositivo de entrada, como pressionar um botão do mouse, acione os eventos de pré-visualização e de propagação roteados em sequência. Primeiro, o evento de visualização é gerado e completa seu percurso. Após a conclusão do evento de visualização, o evento de borbulhamento é acionado e completa seu percurso. A RaiseEvent chamada de método na classe de implementação que gera o evento borbulhante reutiliza os dados do evento de visualização para o evento de bolhas.
Um evento de entrada de visualização marcado como manipulado não invocará manipuladores de eventos normalmente registrados para o restante da rota de visualização e o evento de borbulhamento emparelhado não será gerado. Esse comportamento de tratamento é útil para designers de controles compostos que desejam que eventos de entrada baseados em teste de acerto ou eventos de entrada baseados em foco sejam relatados no nível superior do controle. Os elementos de nível superior do controle têm a oportunidade de lidar com eventos de visualização de classe de subcomponentes de controle para "substituí-los" por um evento específico do controle de nível superior.
Para ilustrar como o processamento de eventos de entrada funciona, considere o exemplo de evento de entrada a seguir. Na ilustração da árvore a seguir, leaf element #2
é a origem dos eventos emparelhados e PreviewMouseDown
da origemMouseDown
:
A ordem do processamento de eventos após uma ação de mouse para baixo no elemento folha nº 2 é:
-
PreviewMouseDown
evento de túnel no elemento raiz. -
PreviewMouseDown
evento de tunelamento no elemento intermediário nº 1. -
PreviewMouseDown
evento de tunelamento no elemento folha nº 2, que é o elemento de origem. -
MouseDown
evento de bolhas no elemento folha nº 2, que é o elemento de origem. -
MouseDown
evento de borbulha no elemento intermediário nº 1. -
MouseDown
evento de propagação no elemento raiz.
O delegado do manipulador de eventos roteado fornece referências ao objeto que gerou o evento e ao objeto em que o manipulador foi invocado. O objeto que originalmente gerou o evento é relatado pela Source propriedade nos dados do evento. O objeto em que o manipulador foi invocado é relatado pelo parâmetro remetente . Para qualquer instância de evento roteada, o objeto que gerou o evento não é alterado à medida que o evento percorre a árvore de elementos, mas o sender
faz. Nas etapas 3 e 4 do diagrama anterior, Source
e sender
são o mesmo objeto.
Se o manipulador de eventos de entrada concluir a lógica específica do aplicativo necessária para resolver o evento, você deverá marcar o evento de entrada como manipulado. Normalmente, depois que um evento de entrada é marcado Handled, os manipuladores mais ao longo da rota de evento não são invocados. No entanto, os manipuladores de eventos de entrada registrados com o handledEventsToo
parâmetro definido serão true
invocados mesmo quando o evento for marcado como manipulado. Para obter mais informações, consulte Eventos de Visualização e Marcar eventos roteados como tratados e tratamento de classe.
O conceito de pares de eventos de visualização e borbulhante, com dados de eventos compartilhados e com a elevação sequencial do evento de visualização seguida pelo evento de borbulhante, aplica-se apenas a alguns eventos de entrada do WPF e não a todos os eventos roteados. Se você implementar seu próprio evento de entrada para resolver um cenário avançado, considere seguir a abordagem de par de eventos de entrada do WPF.
Se você estiver implementando seu próprio controle composto que responde a eventos de entrada, considere usar eventos de visualização para suprimir e substituir eventos de entrada gerados em subcomponentes por um evento de nível superior que represente o controle completo. Para obter mais informações, consulte Marcando eventos roteado como manipulados e manipulação de classe.
Para obter mais informações sobre o sistema de entrada do WPF e como entradas e eventos interagem em cenários típicos de aplicativo, consulte a visão geral de entrada
EventSetters e EventTriggers
Nos estilos de marcação, você pode incluir a sintaxe de tratamento de eventos XAML pré-declarada utilizando um EventSetter. Quando o XAML é processado, o manipulador referenciado é adicionado à instância estilizada. Você só pode declarar um evento roteado EventSetter
. No exemplo a seguir, o método de manipulador de eventos referenciado ApplyButtonStyle
é implementado em code-behind.
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<EventSetter Event="Click" Handler="ApplyButtonStyle"/>
</Style>
</StackPanel.Resources>
<Button>Click me</Button>
<Button Click="Button_Click">Click me</Button>
</StackPanel>
É provável que o Style
nó já contenha outras informações de estilo que pertencem aos controles do tipo especificado, e ter o EventSetter como parte desses estilos promove a reutilização de código mesmo no nível de marcação. Além disso, um EventSetter
abstrai os nomes de métodos de manipuladores do contexto geral do aplicativo e da marcação da página.
Outra sintaxe especializada que combina os recursos de evento roteado e animação do WPF é um EventTrigger. Assim como acontece com o EventSetter
, você só pode declarar um EventTrigger
para um evento roteado. Normalmente, um EventTrigger
é declarado como parte de um estilo, mas um EventTrigger
pode ser declarado em elementos de nível de página como parte da Triggers coleção ou em um ControlTemplate. Um EventTrigger
permite que você especifique um Storyboard que é executado sempre que um evento roteado atinge um elemento em sua rota que declara um EventTrigger
para esse evento. A vantagem de um EventTrigger
sobre apenas lidar com o evento e fazer com que ele inicie um storyboard existente é que um EventTrigger
fornece melhor controle sobre o storyboard e seu comportamento em tempo de execução. Para obter mais informações, consulte Usar gatilhos de evento para controlar um storyboard após o início
Mais sobre eventos roteados
Você pode usar os conceitos e as orientações neste artigo como ponto de partida ao criar eventos roteados personalizados em suas próprias classes. Você também pode dar suporte a seus eventos personalizados com classes de dados de eventos especializados e delegados. Um proprietário de evento roteado pode ser qualquer classe, mas os eventos roteados devem ser gerados e tratados por classes derivadas de UIElement ou ContentElement para serem úteis. Para obter mais informações sobre eventos personalizados, consulte Criar um evento roteado personalizado.
Consulte também
.NET Desktop feedback