Como criar um evento roteado personalizado (WPF .NET)
Os desenvolvedores de aplicativos do Windows Presentation Foundation (WPF) e os autores de componentes podem criar eventos roteados personalizados para estender a funcionalidade dos eventos CLR (Common Language Runtime). Para obter informações sobre recursos de eventos roteados, consulte Por que usar eventos roteados. Este artigo aborda as noções básicas da criação de um evento roteado personalizado.
Pré-requisitos
O artigo pressupõe um conhecimento básico de eventos roteados e que você leu Visão geral de eventos roteados. Para seguir os exemplos neste artigo, é útil se você estiver familiarizado com XAML (Extensible Application Markup Language) e souber como escrever aplicativos WPF (Windows Presentation Foundation).
Etapas de evento roteadas
As etapas básicas para criar um evento roteado são:
Registre um RoutedEvent usando o RegisterRoutedEvent método.
A chamada de registro retorna uma
RoutedEvent
instância, conhecida como identificador de evento roteado, que contém o nome do evento registrado, a estratégia de roteamento e outros detalhes do evento. Atribua o identificador a um campo estático somente leitura. Por convenção:- O identificador de um evento roteado com uma estratégia de propagação é chamado
<event name>Event
. Por exemplo, se o nome do evento forTap
, o identificador deverá ser nomeadoTapEvent
. - O identificador de um evento roteado com uma estratégia de tunelamento é denominado
Preview<event name>Event
. Por exemplo, se o nome do evento forTap
, o identificador deverá ser nomeadoPreviewTapEvent
.
- O identificador de um evento roteado com uma estratégia de propagação é chamado
Defina acessadores de evento de adição e remoção de CLR. Sem acessadores de eventos CLR, você só poderá adicionar ou remover manipuladores de eventos por meio de chamadas diretas para os UIElement.AddHandler métodos and UIElement.RemoveHandler . Com acessadores de eventos CLR, você obtém estes mecanismos de atribuição de manipulador de eventos:
- Para XAML (Extensible Application Markup Language), você pode usar a sintaxe de atributo para adicionar manipuladores de eventos.
- Para C#, você pode usar os
+=
operadores and-=
para adicionar ou remover manipuladores de eventos. - Para VB, você pode usar as instruções AddHandler e RemoveHandler para adicionar ou remover manipuladores de eventos.
Adicione lógica personalizada para acionar seu evento roteado. Por exemplo, sua lógica pode disparar o evento com base na entrada do usuário e no estado do aplicativo.
Exemplo
O exemplo a seguir implementa a CustomButton
classe em uma biblioteca de controle personalizada. A CustomButton
classe, que deriva de Button:
- Registra um RoutedEvent nome
ConditionalClick
usando o método e especifica a estratégia de propagação durante o RegisterRoutedEvent registro. - Atribui a
RoutedEvent
instância retornada da chamada de registro a um campo estático somente leitura chamadoConditionalClickEvent
. - Define acessadores de evento de adição e remoção de CLR.
- Adiciona lógica personalizada para gerar o evento roteado personalizado quando o é clicado
CustomButton
e uma condição externa se aplica. Embora o código de exemplo gere oConditionalClick
evento roteado de dentro do método virtual substituídoOnClick
, você pode gerar seu evento da maneira que escolher.
public class CustomButton : Button
{
// Register a custom routed event using the Bubble routing strategy.
public static readonly RoutedEvent ConditionalClickEvent = EventManager.RegisterRoutedEvent(
name: "ConditionalClick",
routingStrategy: RoutingStrategy.Bubble,
handlerType: typeof(RoutedEventHandler),
ownerType: typeof(CustomButton));
// Provide CLR accessors for assigning an event handler.
public event RoutedEventHandler ConditionalClick
{
add { AddHandler(ConditionalClickEvent, value); }
remove { RemoveHandler(ConditionalClickEvent, value); }
}
void RaiseCustomRoutedEvent()
{
// Create a RoutedEventArgs instance.
RoutedEventArgs routedEventArgs = new(routedEvent: ConditionalClickEvent);
// Raise the event, which will bubble up through the element tree.
RaiseEvent(routedEventArgs);
}
// For demo purposes, we use the Click event as a trigger.
protected override void OnClick()
{
// Some condition combined with the Click event will trigger the ConditionalClick event.
if (DateTime.Now > new DateTime())
RaiseCustomRoutedEvent();
// Call the base class OnClick() method so Click event subscribers are notified.
base.OnClick();
}
}
Public Class CustomButton
Inherits Button
' Register a custom routed event with the Bubble routing strategy.
Public Shared ReadOnly ConditionalClickEvent As RoutedEvent = EventManager.RegisterRoutedEvent(
name:="ConditionalClick",
routingStrategy:=RoutingStrategy.Bubble,
handlerType:=GetType(RoutedEventHandler),
ownerType:=GetType(CustomButton))
' Provide CLR accessors to support event handler assignment.
Public Custom Event ConditionalClick As RoutedEventHandler
AddHandler(value As RoutedEventHandler)
[AddHandler](ConditionalClickEvent, value)
End AddHandler
RemoveHandler(value As RoutedEventHandler)
[RemoveHandler](ConditionalClickEvent, value)
End RemoveHandler
RaiseEvent(sender As Object, e As RoutedEventArgs)
[RaiseEvent](e)
End RaiseEvent
End Event
Private Sub RaiseCustomRoutedEvent()
' Create a RoutedEventArgs instance.
Dim routedEventArgs As New RoutedEventArgs(routedEvent:=ConditionalClickEvent)
' Raise the event, which will bubble up through the element tree.
[RaiseEvent](routedEventArgs)
End Sub
' For demo purposes, we use the Click event as a trigger.
Protected Overrides Sub OnClick()
' Some condition combined with the Click event will trigger the ConditionalClick event.
If Date.Now > New DateTime() Then RaiseCustomRoutedEvent()
' Call the base class OnClick() method so Click event subscribers are notified.
MyBase.OnClick()
End Sub
End Class
O exemplo inclui um aplicativo WPF separado que usa marcação XAML para adicionar uma instância de the CustomButton
a um StackPanel, e atribuir o Handler_ConditionalClick
método como o ConditionalClick
manipulador de eventos para os CustomButton
elementos and StackPanel1
.
<Window x:Class="CodeSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom="clr-namespace:WpfControl;assembly=WpfControlLibrary"
Title="How to create a custom routed event" Height="100" Width="300">
<StackPanel Name="StackPanel1" custom:CustomButton.ConditionalClick="Handler_ConditionalClick">
<custom:CustomButton
Name="customButton"
ConditionalClick="Handler_ConditionalClick"
Content="Click to trigger a custom routed event"
Background="LightGray">
</custom:CustomButton>
</StackPanel>
</Window>
No code-behind, o aplicativo WPF define o Handler_ConditionalClick
método do manipulador de eventos. Os métodos do manipulador de eventos só podem ser implementados no code-behind.
// The ConditionalClick event handler.
private void Handler_ConditionalClick(object sender, RoutedEventArgs e)
{
string senderName = ((FrameworkElement)sender).Name;
string sourceName = ((FrameworkElement)e.Source).Name;
Debug.WriteLine($"Routed event handler attached to {senderName}, " +
$"triggered by the ConditionalClick routed event raised on {sourceName}.");
}
// Debug output when CustomButton is clicked:
// Routed event handler attached to CustomButton,
// triggered by the ConditionalClick routed event raised on CustomButton.
// Routed event handler attached to StackPanel1,
// triggered by the ConditionalClick routed event raised on CustomButton.
' The ConditionalClick event handler.
Private Sub Handler_ConditionalClick(sender As Object, e As RoutedEventArgs)
Dim sourceName As String = CType(e.Source, FrameworkElement).Name
Dim senderName As String = CType(sender, FrameworkElement).Name
Debug.WriteLine($"Routed event handler attached to {senderName}, " +
$"triggered by the ConditionalClick routed event raised on {sourceName}.")
End Sub
' Debug output when CustomButton is clicked:
' Routed event handler attached to CustomButton,
' triggered by the ConditionalClick routed event raised on CustomButton.
' Routed event handler attached to StackPanel1,
' triggered by the ConditionalClick routed event raised on CustomButton.
Quando CustomButton
é clicado:
- O
ConditionalClick
evento roteado é gerado emCustomButton
. - O
Handler_ConditionalClick
manipulador de eventos anexado éCustomButton
disparado. - O
ConditionalClick
evento roteado percorre a árvore de elementos atéStackPanel1
. - O
Handler_ConditionalClick
manipulador de eventos anexado éStackPanel1
disparado. - O
ConditionalClick
evento roteado continua na árvore de elementos, potencialmente acionando outrosConditionalClick
manipuladores de eventos anexados a outros elementos percorridos.
O Handler_ConditionalClick
manipulador de eventos obtém as seguintes informações sobre o evento que o acionou:
- O objeto sender , que é o elemento ao qual o manipulador de eventos está anexado. Será
sender
CustomButton
a primeira vez que o manipulador será executado eStackPanel1
a segunda vez. - O RoutedEventArgs.Source objeto, que é o elemento que originalmente gerou o evento. Neste exemplo, o
Source
é sempreCustomButton
.
Observação
Uma diferença fundamental entre um evento roteado e um evento CLR é que um evento roteado percorre a árvore de elementos, procurando manipuladores, enquanto um evento CLR não atravessa a árvore de elementos e os manipuladores só podem anexar ao objeto de origem que gerou o evento. Como resultado, um evento sender
roteado pode ser qualquer elemento percorrido na árvore de elementos.
Você pode criar um evento de túnel da mesma forma que um evento de propagação, exceto que você definirá a estratégia de roteamento na chamada de registro de evento como Tunnel. Para obter mais informações sobre eventos de túnel, consulte Eventos de entrada do WPF.
Confira também
.NET Desktop feedback