Compartir a través de


Resumen de los eventos adjuntos

Extensible Application Markup Language (XAML) define un componente de lenguaje y un tipo de evento denominado evento adjunto. Los eventos adjuntos se pueden usar para definir un nuevo evento enrutado en una clase que no sea de elemento y generar ese evento en cualquier elemento del árbol. Para ello, debe registrar el evento adjunto como un evento enrutado y proporcionar código de respaldo específico que admita la funcionalidad de eventos adjuntos. Dado que los eventos adjuntos se registran como eventos enrutados, cuando se generan en un elemento, se propagan a través del árbol de elementos.

Prerrequisitos

En el artículo se da por supuesto un conocimiento básico de los eventos enrutados de Windows Presentation Foundation (WPF) y que has leído Información general sobre eventos enrutados y XAML en WPF. Para seguir los ejemplos de este artículo, le ayuda si está familiarizado con XAML y sabe cómo escribir aplicaciones WPF.

Sintaxis de eventos adjuntos

En la sintaxis XAML, un evento adjunto se especifica mediante su nombre de evento y su tipo de propietario, en forma de <owner type>.<event name>. Dado que el nombre del evento se califica con el nombre de su tipo de propietario, la sintaxis permite que el evento se adjunte a cualquier elemento que se pueda instanciar. Esta sintaxis también es aplicable a los controladores para eventos enrutados normales que se adjuntan a un elemento arbitrario a lo largo de la ruta del evento.

La siguiente sintaxis de atributo XAML vincula el controlador AquariumFilter_Clean para el evento vinculado AquariumFilter.Clean al elemento aquarium1.

<aqua:Aquarium x:Name="aquarium1" Height="300" Width="400" aqua:AquariumFilter.Clean="AquariumFilter_Clean"/>

En este ejemplo, el prefijo aqua: es necesario porque las clases AquariumFilter y Aquarium existen en otro espacio de nombres y ensamblado de Common Language Runtime (CLR).

También puede adjuntar controladores para eventos vinculados en el código subyacente. Para ello, llame al AddHandler método en el objeto al que el controlador se adjunta y pase como parámetros el identificador de evento y el controlador al método.

Cómo implementa WPF eventos anexos

Los eventos adjuntos de WPF se implementan como eventos enrutados respaldados por un RoutedEvent campo. Como resultado, los eventos adjuntos se propagan a través del árbol de elementos después de ser activados. Por lo general, el objeto que genera el evento adjunto, conocido como origen del evento, es un origen del sistema o del servicio. Los orígenes de sistema o servicio no forman parte directa del árbol de elementos. Para otros eventos adjuntos, el origen del evento puede ser un elemento del árbol, como un componente dentro de un control compuesto.

Escenarios de eventos adjuntos

En WPF, los eventos adjuntos se utilizan en áreas específicas de características donde existe una abstracción de nivel de servicio. Por ejemplo, WPF hace uso de eventos adjuntos habilitados por las clases estáticas Mouse o Validation. Las clases que interactúan o usan un servicio pueden interactuar con un evento mediante la sintaxis de evento adjunta o exponer el evento adjunto como un evento enrutado. Esta última opción forma parte de cómo una clase podría integrar las funcionalidades del servicio.

El sistema de entrada de WPF usa eventos adjuntos ampliamente. Sin embargo, casi la totalidad de esos eventos conectados se presentan como eventos enrutados no asociados equivalentes a través de elementos base. Cada evento de entrada enrutado es un miembro de la clase base de elemento y está respaldado por un evento CLR "wrapper". Rara vez usará o gestionará los eventos adjuntos directamente. Por ejemplo, es más fácil controlar el evento adjunto Mouse.MouseDown subyacente en un UIElement a través del evento enrutado equivalente UIElement.MouseDown que mediante la sintaxis de eventos adjunta en XAML o código subyacente.

Los eventos adjuntos sirven para un propósito de arquitectura habilitando la expansión futura de los dispositivos de entrada. Por ejemplo, un nuevo dispositivo de entrada solo tendría que generar Mouse.MouseDown para simular la entrada del mouse y no tendría que derivar de Mouse para hacerlo. Este escenario implica el control de código del evento, ya que el control XAML del evento adjunto no sería relevante.

Control de un evento adjunto

El proceso para codificar y controlar un evento adjunto es básicamente el mismo que para un evento enrutado no asociado.

Como se indicó anteriormente, los eventos adjuntos de WPF existentes normalmente no están diseñados para administrarse directamente en WPF. Con más frecuencia, el propósito de un evento adjunto es permitir que un elemento dentro de un control compuesto notifique su estado a un elemento primario dentro del control. En ese escenario, el evento se genera en el código y se basa en el control de clases en la clase primaria pertinente. Por ejemplo, se espera que los elementos dentro de un Selector generen el evento adjunto Selected, que luego es controlada por la clase Selector. La Selector clase convierte potencialmente el Selected evento en el SelectionChanged evento enrutado. Para obtener más información sobre los eventos enrutados y el control de clases, vea Marcar eventos enrutados como controlados y control de clases.

Definición de un evento adjunto personalizado

Si deriva de clases base comunes de WPF, puede implementar su evento adjunto personalizado incluyendo dos métodos de acceso en su clase. Estos métodos son:

  • Un método Add<event name>Handler , con un primer parámetro que es el elemento en el que está asociado el controlador de eventos y un segundo parámetro que es el controlador de eventos que se va a agregar. El método debe ser public y static, sin ningún valor devuelto. El método llama al método de la clase base AddHandler, pasando el evento enrutado y el controlador como argumentos. Este método admite la sintaxis de atributo XAML para adjuntar un controlador de eventos a un elemento. Este método también permite el acceso de código al almacén del controlador de eventos para el evento adjunto.

  • Método Remove<event name>Handler , con un primer parámetro que es el elemento en el que está asociado el controlador de eventos y un segundo parámetro que es el controlador de eventos que se va a quitar. El método debe ser public y static, sin ningún valor devuelto. El método llama al método de la clase base RemoveHandler, pasando el evento enrutado y el controlador como argumentos. Este método permite el acceso de código al almacén del controlador de eventos para el evento adjunto.

WPF implementa eventos adjuntos como eventos enrutados porque el identificador de un RoutedEvent elemento está definido por el sistema de eventos WPF. Además, el enrutamiento de un evento es una extensión natural del concepto a nivel de lenguaje de XAML de un evento adjunto. Esta estrategia de implementación restringe el control de eventos adjuntos a UIElement clases derivadas o ContentElement clases derivadas, ya que solo esas clases tienen AddHandler implementaciones.

Por ejemplo, el código siguiente define el Clean evento adjunto en la AquariumFilter clase owner, que no es una clase de elemento. El código define el evento adjunto como un evento enrutado e implementa los métodos de acceso necesarios.

public class AquariumFilter
{
    // Register a custom routed event using the bubble routing strategy.
    public static readonly RoutedEvent CleanEvent = EventManager.RegisterRoutedEvent(
        "Clean", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AquariumFilter));

    // Provide an add handler accessor method for the Clean event.
    public static void AddCleanHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
    {
        if (dependencyObject is not UIElement uiElement)
            return;

        uiElement.AddHandler(CleanEvent, handler);
    }

    // Provide a remove handler accessor method for the Clean event.
    public static void RemoveCleanHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
    {
        if (dependencyObject is not UIElement uiElement)
            return;

        uiElement.RemoveHandler(CleanEvent, handler);
    }
}
Public Class AquariumFilter

    ' Register a custom routed event using the bubble routing strategy.
    Public Shared ReadOnly CleanEvent As RoutedEvent = EventManager.RegisterRoutedEvent(
        "Clean", RoutingStrategy.Bubble, GetType(RoutedEventHandler), GetType(AquariumFilter))

    ' Provide an add handler accessor method for the Clean event.
    Public Shared Sub AddCleanHandler(dependencyObject As DependencyObject, handler As RoutedEventHandler)
        Dim uiElement As UIElement = TryCast(dependencyObject, UIElement)

        If uiElement IsNot Nothing Then
            uiElement.[AddHandler](CleanEvent, handler)
        End If
    End Sub

    ' Provide a remove handler accessor method for the Clean event.
    Public Shared Sub RemoveCleanHandler(dependencyObject As DependencyObject, handler As RoutedEventHandler)
        Dim uiElement As UIElement = TryCast(dependencyObject, UIElement)

        If uiElement IsNot Nothing Then
            uiElement.[RemoveHandler](CleanEvent, handler)
        End If
    End Sub

End Class

El RegisterRoutedEvent método que devuelve el identificador de evento adjunto es el mismo método que se usa para registrar eventos enrutados no adjuntos. Los eventos enrutados adjuntos y no adjuntos se registran en un almacenamiento interno centralizado. Esta implementación del almacén de eventos habilita el concepto de "eventos como interfaz" que se describe en Introducción a eventos enrutados.

A diferencia del "envoltorio" del evento CLR usado para eventos enrutados no adjuntos, los métodos de accessores de eventos adjuntos se pueden implementar en clases que no derivan de UIElement o ContentElement. Esto es posible porque el código de respaldo de eventos adjunto llama a los UIElement.AddHandler métodos y UIElement.RemoveHandler en una instancia pasada UIElement . Por el contrario, la interfaz CLR para eventos enrutados no vinculados llama a esos métodos directamente en la clase propietaria, de modo que esa clase debe derivar de UIElement.

Lanzar un evento adjunto de WPF

El proceso para activar un evento adjunto es esencialmente el mismo que para un evento enrutado no adjunto.

Normalmente, el código no necesitará generar ningún evento adjunto definido por WPF existente, ya que esos eventos siguen el modelo conceptual general de "servicio". En ese modelo, las clases de servicio, como InputManager, son responsables de generar eventos adjuntos definidos por WPF.

Al definir un evento adjunto personalizado mediante el modelo de WPF de basar eventos adjuntos en eventos enrutados, use el UIElement.RaiseEvent método para generar un evento adjunto en cualquiera UIElement o ContentElement. Al generar un evento enrutado, ya sea adjunto o no, es necesario designar un elemento en el árbol de elementos como origen del evento. A continuación, ese origen se notifica como el RaiseEvent llamador. Por ejemplo, para activar el evento enrutado adjunto AquariumFilter.Clean en aquarium1:

aquarium1.RaiseEvent(new RoutedEventArgs(AquariumFilter.CleanEvent));
aquarium1.[RaiseEvent](New RoutedEventArgs(AquariumFilter.CleanEvent))

En el ejemplo anterior, aquarium1 es el origen del evento.

Consulte también