Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Los desarrolladores de aplicaciones y 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, vea Por qué usar eventos enrutados. En este artículo se describen los conceptos básicos de la creación de un evento enrutado personalizado.
Prerrequisitos
El artículo supone un conocimiento básico de los eventos enrutados y que hayas leído Información general sobre eventos enrutados. Para seguir los ejemplos de este artículo, le ayuda si está familiarizado con el lenguaje de marcado extensible de aplicaciones (XAML) y sabe cómo escribir aplicaciones de Windows Presentation Foundation (WPF).
Pasos de eventos enrutados
Los pasos básicos para crear un evento enrutado son:
Registre un RoutedEvent mediante el RegisterRoutedEvent método .
La llamada de registro devuelve una
RoutedEvent
instancia, 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 de solo lectura estático. Por convención:- El identificador de un evento enrutado con una estrategia de burbujeo 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 burbujeo se denomina
Defina CLR add y remove accesores de eventos. Sin accesores de eventos CLR, solo podrá agregar o quitar controladores de eventos a través de llamadas directas a los métodos UIElement.AddHandler y UIElement.RemoveHandler. Con los descriptores de acceso de eventos CLR, obtendrá estos mecanismos para la asignación de controladores de eventos:
- Para lenguaje de marcado de aplicaciones extensibles (XAML), puedes 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 activar su 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 CustomButton
clase en una biblioteca de controles personalizada. La CustomButton
clase , que deriva de Button:
- Registra un RoutedEvent denominado
ConditionalClick
usando el método RegisterRoutedEvent y especifica la estrategia de propagación durante el registro. - Asigna la
RoutedEvent
instancia devuelta desde la llamada de registro a un campo estático de solo lectura denominadoConditionalClickEvent
. - Define los descriptores de acceso de eventos de CLR add y remove.
- Agrega lógica personalizada para activar el evento enrutado personalizado cuando se hace clic en
CustomButton
y se cumple una condición externa. Aunque el código de ejemplo genera elConditionalClick
evento enrutado 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 Handler_ConditionalClick
método de controlador de eventos. Los métodos del 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.
Al hacer clic en CustomButton
:
- El
ConditionalClick
evento enrutado se genera enCustomButton
. - El
Handler_ConditionalClick
controlador de eventos asociado aCustomButton
se desencadena. - El
ConditionalClick
evento enrutado atraviesa el árbol de elementos aStackPanel1
. - El
Handler_ConditionalClick
controlador de eventos asociado aStackPanel1
se desencadena. - El
ConditionalClick
evento enrutado continúa hacia arriba en el árbol de elementos, potencialmente desencadenando otrosConditionalClick
controladores de eventos asociados a otros elementos recorridos.
El Handler_ConditionalClick
controlador de eventos obtiene la siguiente información sobre el evento que lo desencadenó:
- Objeto remitente , que es el elemento al que está asociado el controlador de eventos. El valor de
sender
seráCustomButton
la primera vez que se ejecute el controlador yStackPanel1
la segunda. - Objeto RoutedEventArgs.Source , que es el elemento que generó originalmente el evento. En este ejemplo, el
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 pueden asociarse al objeto de origen que generó el evento. Como resultado, un evento sender
enrutado puede ser cualquier elemento recorrido 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 obtener más información sobre los eventos de tunelización, vea Eventos de entrada de WPF.
Consulte también
.NET Desktop feedback