Cómo crear un evento enrutado personalizado (WPF .NET)
Los desarrolladores de la aplicación y los autores de componentes de Windows Presentation Foundation (WPF) pueden crear eventos enrutados personalizados para ampliar la funcionalidad de los eventos de Common Language Runtime (CLR). Para obtener información sobre las funcionalidades de eventos enrutados, consulte Por qué usar eventos enrutados. Este artículo cubre los aspectos básicos de la creación de un evento enrutado personalizado.
Requisitos previos
En el artículo se da por supuesto un conocimiento básico de los eventos enrutados y que ha leído Información general sobre eventos enrutados. Para seguir los ejemplos de este artículo, le ayudará estar familiarizado con el lenguaje XAML y saber cómo escribir aplicaciones de Windows Presentation Foundation (WPF).
Pasos de eventos enrutados
Los pasos básicos para crear un evento enrutado son los siguientes:
Registre RoutedEvent mediante el método RegisterRoutedEvent.
La llamada de registro devuelve una instancia
RoutedEvent
, conocida como identificador de evento enrutado, que contiene el nombre del evento registrado, la estrategia de enrutamiento y otros detalles del evento. Asigne el identificador a un campo estático de solo lectura. Por convención:- El identificador de un evento enrutado con una estrategia de propagación se denomina
<event name>Event
. Por ejemplo, si el nombre del evento esTap
, el identificador debe denominarseTapEvent
. - El identificador de un evento enrutado con una estrategia de tunelización se denomina
Preview<event name>Event
. Por ejemplo, si el nombre del evento esTap
, el identificador debe denominarsePreviewTapEvent
.
- El identificador de un evento enrutado con una estrategia de propagación se denomina
Defina los descriptores de acceso de evento de CLR add y remove. Sin los descriptores de acceso de evento CLR, solo podrá añadir o quitar controladores de evento mediante llamadas directas a los métodos UIElement.AddHandler y UIElement.RemoveHandler. Con los descriptores de acceso de evento CLR, se obtienen estos mecanismos de asignación de controlador de eventos:
- Para el lenguaje XAML, puede usar la sintaxis de atributo para agregar controladores de eventos.
- Para C#, puede usar los operadores
+=
y-=
para agregar o quitar controladores de eventos. - Para VB, puede usar las instrucciones AddHandler y RemoveHandler para agregar o quitar controladores de eventos.
Agregue lógica personalizada para desencadenar el evento enrutado. Por ejemplo, la lógica podría desencadenar el evento en función de la entrada del usuario y el estado de la aplicación.
Ejemplo
En el ejemplo siguiente se implementa la clase CustomButton
en una biblioteca de control personalizado. La clase CustomButton
, que se deriva de Button:
- Registra un objeto RoutedEvent con nombre
ConditionalClick
mediante el método RegisterRoutedEvent y especifica la estrategia de propagación durante el registro. - Asigna la instancia
RoutedEvent
devuelta desde la llamada de registro a un campo estático de solo lectura denominadoConditionalClickEvent
. - Define los descriptores de acceso de evento CLR add y remove.
- Agrega lógica personalizada para generar el evento enrutado personalizado cuando se hace clic en
CustomButton
y se aplica una condición externa. Aunque el código de ejemplo genera el evento enrutadoConditionalClick
desde dentro del método virtual invalidadoOnClick
, puede generar el evento de cualquier manera que elija.
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
En el ejemplo se incluye una aplicación WPF independiente que usa el marcado XAML para agregar una instancia de CustomButton
a StackPanel y para asignar el método Handler_ConditionalClick
como controlador de eventos ConditionalClick
para los elementos CustomButton
y 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>
En el código subyacente, la aplicación WPF define el método de controlador de eventos Handler_ConditionalClick
. Los métodos de controlador de eventos solo se pueden implementar en código subyacente.
// 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.
Cuando se hace clic en CustomButton
:
- El evento enrutado
ConditionalClick
se genera enCustomButton
. - Se desencadena el controlador de eventos
Handler_ConditionalClick
asociado aCustomButton
. - El evento enrutado
ConditionalClick
recorre el árbol de elementos hastaStackPanel1
. - Se desencadena el controlador de eventos
Handler_ConditionalClick
asociado aStackPanel1
. - El evento enrutado
ConditionalClick
continúa hacia arriba en el árbol de elementos, lo que podría desencadenar otros controladores de eventosConditionalClick
asociados a otros elementos recorridos.
El controlador de eventos Handler_ConditionalClick
obtiene la siguiente información sobre el evento que lo desencadenó:
- Objeto emisor, que es el elemento al que está asociado el controlador de eventos. El objeto
sender
seráCustomButton
la primera vez que se ejecute el controlador, yStackPanel1
la segunda. - El objeto RoutedEventArgs.Source, que es el elemento que generó originalmente el evento. En este ejemplo,
Source
siempre esCustomButton
.
Nota
Una diferencia clave entre un evento enrutado y un evento CLR es que un evento enrutado atraviesa el árbol de elementos, buscando controladores, mientras que un evento CLR no atraviesa el árbol de elementos, y los controladores solo se pueden adjuntar al objeto de origen que generó el evento. Como resultado, un evento enrutado sender
puede ser cualquier elemento transversal en el árbol de elementos.
Puede crear un evento de tunelización del mismo modo que un evento de propagación, salvo que establecerá la estrategia de enrutamiento en la llamada de registro de eventos a Tunnel. Para más información sobre los eventos de tunelización, vea Eventos de entrada de WPF.
Vea también
.NET Desktop feedback