Freigeben über


Übersicht über angefügte Ereignisse

Extensible Application Markup Language (XAML) definiert eine Sprachkomponente und einen Ereignistyp, der als angefügtes Ereignis bezeichnet wird. Angefügte Ereignisse können verwendet werden, um ein neues Routingereignis in einer Nicht-Elementklasse zu definieren und dieses Ereignis für jedes Element in Ihrer Struktur auszulösen. Dazu müssen Sie das angefügte Ereignis als Routingereignis registrieren und spezifischen Sicherungscode bereitstellen, der angefügte Ereignisfunktionen unterstützt. Da angefügte Ereignisse als Routingereignisse registriert sind, verbreiten sie sich, wenn sie auf einem Element ausgelöst werden, durch den Elementbaum.

Voraussetzungen

In diesem Artikel wird davon ausgegangen, dass Sie grundlegende Kenntnisse über Routingereignisse von Windows Presentation Foundation (WPF) haben und die Übersicht über Routingereignisse und XAML in WPF gelesen haben. Um den Beispielen in diesem Artikel zu folgen, hilft es Ihnen, wenn Sie mit XAML vertraut sind und wissen, wie WPF-Anwendungen geschrieben werden.

Syntax des angefügten Ereignisses

In der XAML-Syntax wird ein angefügtes Ereignis über den Ereignisnamen und den Besitzertyp angegeben, wie in der Form von <owner type>.<event name>. Da der Ereignisname mit dem Namen seines Besitzertyps qualifiziert ist, kann das Ereignis an jedes Element angefügt werden, das instanziiert werden kann. Diese Syntax gilt auch für Handler für reguläre Routingereignisse, die entlang der Ereignisroute an ein beliebiges Element angefügt werden.

Die folgende XAML-Attributsyntax fügt den AquariumFilter_Clean Handler für das AquariumFilter.Clean angefügte Ereignis an das aquarium1 Element an:

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

In diesem Beispiel ist das Präfix aqua: erforderlich, da die Klassen AquariumFilter und Aquarium in einem anderen CLR-Namespace und einer anderen Assembly vorhanden sind.

Sie können auch Handler für angefügte Ereignisse im CodeBehind anfügen. Rufen Sie dazu die AddHandler Methode für das Objekt auf, das der Handler anfügen und den Ereignisbezeichner und -handler als Parameter an die Methode übergeben soll.

So implementiert WPF angefügte Ereignisse

Angefügte WPF-Ereignisse werden als Routingereignisse implementiert, die von einem RoutedEvent Feld unterstützt werden. Daher werden angehängte Ereignisse nach ihrem Auslösen durch die Elementstruktur propagiert. Im Allgemeinen ist das Objekt, das das angefügte Ereignis auslöst, das als Ereignisquelle bezeichnet wird, eine System- oder Dienstquelle. System- oder Dienstquellen sind kein direkter Teil der Elementstruktur. Bei anderen angehängten Ereignissen kann die Ereignisquelle ein Element im Baum sein, z. B. eine Komponente innerhalb eines zusammengesetzten Steuerelements.

Szenarien für angefügte Ereignisse

In WPF werden angefügte Ereignisse in bestimmten Featurebereichen verwendet, in denen eine Abstraktion auf Dienstebene vorhanden ist. Beispielsweise verwendet WPF angefügte Ereignisse, die von statischen Mouse oder Validation Klassen aktiviert werden. Klassen, die mit einem Dienst interagieren oder einen Dienst verwenden, können entweder mit einem Ereignis mithilfe einer angefügten Ereignissyntax interagieren oder das angefügte Ereignis als routingfähiges Ereignis anzeigen. Letztere Option ist Teil der Integration der Funktionen des Diensts durch eine Klasse.

Das WPF-Eingabesystem verwendet häufig angefügte Ereignisse. Fast alle angefügten Ereignisse werden jedoch als gleichwertige nicht angefügte Routingereignisse über Basiselemente angezeigt. Jedes Routingeingabeereignis ist ein Element der Basiselementklasse und wird mit einem CLR-Ereignis "wrapper" gesichert. Sie werden angefügte Ereignisse nur selten direkt verwenden oder behandeln. So ist es beispielsweise einfacher, das zugrunde liegende angefügte Mouse.MouseDown Ereignis für ein UIElement über das entsprechende UIElement.MouseDown geroutete Ereignis zu behandeln, als dies mithilfe der angefügten Ereignissyntax in XAML oder Code-Behind zu tun.

Angefügte Ereignisse dienen einem Architekturzweck, indem eine zukünftige Erweiterung von Eingabegeräten ermöglicht wird. Ein neues Eingabegerät müsste zum Beispiel nur Mouse.MouseDown anheben, um Mauseingaben zu simulieren, und es ist nicht erforderlich, sich von Mouse abzuleiten, um dies zu tun. Dieses Szenario umfasst die Codebehandlung des Ereignisses, da die XAML-Behandlung des angefügten Ereignisses nicht relevant wäre.

Behandeln eines gebundenen Ereignisses

Der Prozess zum Codieren und Behandeln eines angefügten Ereignisses ist im Wesentlichen identisch mit einem nicht angefügten Routingereignis.

Wie bereits erwähnt, sind vorhandene angefügte WPF-Ereignisse in der Regel nicht für die direkte Verarbeitung in WPF vorgesehen. Häufiger dient der Zweck eines angefügten Ereignisses darin, einem Element innerhalb eines zusammengesetzten Steuerelements das Melden des Zustands an ein übergeordnetes Element innerhalb des Steuerelements zu ermöglichen. In diesem Szenario wird das Ereignis im Code ausgelöst und basiert auf der Klassenbehandlung in der relevanten übergeordneten Klasse. Beispielsweise wird erwartet, dass Elemente innerhalb eines Selector das angehängte Selected-Ereignis auslösen, das dann klassenspezifisch von der Selector-Klasse behandelt wird. Die Selector Klasse konvertiert das Selected Ereignis potenziell in das SelectionChanged Routingereignis. Weitere Informationen zu Routingereignissen und klassenverarbeitung finden Sie unter Kennzeichnen von Routingereignissen als behandelt und Klassenbehandlung.

Definieren Sie ein benutzerdefiniertes angeschlossenes Ereignis

Wenn Sie von allgemeinen WPF-Basisklassen abgeleitet werden, können Sie Ihr benutzerdefiniertes angefügtes Ereignis implementieren, indem Sie zwei Accessormethoden in Ihre Klasse einschließen. Diese Methoden sind:

  • Eine Methode zur Hinzufügung eines Ereignis-Handlers, mit einem ersten Parameter, der das Element angibt, an das der Ereignis-Handler angefügt wird, und einem zweiten Parameter, der den hinzuzufügenden Ereignis-Handler darstellt. Die Methode muss public und static sein, ohne Rückgabewert. Die Methode ruft die AddHandler Basisklassenmethode auf und übergibt das Routingereignis und den Handler als Argumente. Diese Methode unterstützt die XAML-Attributsyntax zum Anfügen eines Ereignishandlers an ein Element. Diese Methode ermöglicht auch den Codezugriff auf den Ereignishandlerspeicher für das angefügte Ereignis.

  • Eine RemoveEventHandler-Methode<> mit einem ersten Parameter, der das Element ist, an das der Ereignishandler hinzugefügt ist, und einen zweiten Parameter, der der zu entfernende Ereignishandler ist. Die Methode muss public und static sein, ohne Rückgabewert. Die Methode ruft die RemoveHandler Basisklassenmethode auf und übergibt das Routingereignis und den Handler als Argumente. Diese Methode ermöglicht den Codezugriff auf den Ereignishandlerspeicher für das angefügte Ereignis.

WPF implementiert angefügte Ereignisse als Routingereignisse, da der Bezeichner für ein RoutedEvent Ereignis vom WPF-Ereignissystem definiert wird. Außerdem ist das Routing eines Ereignisses eine natürliche Erweiterung des XAML-Sprachebenenkonzepts eines angefügten Ereignisses. Diese Implementierungsstrategie schränkt die Behandlung von angefügten Ereignissen auf UIElement oder ContentElement abgeleitete Klassen ein, da nur diese Klassen AddHandler Implementierungen haben.

Der folgende Code definiert beispielsweise das Clean angefügte Ereignis für die AquariumFilter Besitzerklasse, bei dem es sich nicht um eine Elementklasse handelt. Der Code definiert das angefügte Ereignis als Routingereignis und implementiert die erforderlichen Accessormethoden.

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

Die RegisterRoutedEvent Methode, die den angefügten Ereignisbezeichner zurückgibt, ist die gleiche Methode, mit der nicht angefügte Routingereignisse registriert werden. Sowohl angefügte als auch nicht angefügte Routingereignisse werden in einem zentralen internen Speicher registriert. Diese Ereignisspeicherimplementierung ermöglicht das Konzept "Ereignisse als Schnittstelle", das in der Übersicht über Routingereignisse erläutert wird.

Im Gegensatz zum CLR-Ereignis-"Wrapper", der zum Sichern von nicht angefügten gerouteten Ereignissen verwendet wird, können die Methoden des angefügten Ereignisaccessors in Klassen implementiert werden, die nicht von UIElement oder ContentElement abgeleitet werden. Dies ist möglich, da der angefügte Ereignissicherungscode die UIElement.AddHandler und UIElement.RemoveHandler Methoden für eine übergebene UIElement Instanz aufruft. Im Gegensatz dazu ruft der CLR-Wrapper für nicht angefügte Routingereignisse diese Methoden direkt in der eigenen Klasse auf, sodass die Klasse von UIElement.

Auslösen eines angefügten WPF-Ereignisses

Der Prozess zum Auslösen eines angefügten Ereignisses ist im Wesentlichen identisch mit einem nicht angefügten Routingereignis.

Normalerweise muss Ihr Code keine vorhandenen WPF-definierten angefügten Ereignisse auslösen, da diese Ereignisse dem allgemeinen konzeptuellen Modell "Service" folgen. In diesem Modell sind Dienstklassen wie z. B. InputManager für das Auslösen von WPF-definierten angefügten Ereignissen verantwortlich.

Verwenden Sie beim Definieren eines benutzerdefinierten angefügten Ereignisses mithilfe des WPF-Modells, bei dem angefügte Ereignisse auf routeten Ereignissen basieren, die UIElement.RaiseEvent-Methode, um ein angefügtes Ereignis auf einem UIElement oder ContentElement auszulösen. Beim Auslösen eines Routingereignisses, unabhängig davon, ob es angefügt ist oder nicht, müssen Sie ein Element in Der Elementstruktur als Ereignisquelle festlegen. Diese Quelle wird dann als RaiseEvent Aufrufer gemeldet. Zum Beispiel, um das AquariumFilter.Clean angefügte Routingereignis auf aquarium1 auszulösen:

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

Im vorherigen Beispiel aquarium1 ist die Ereignisquelle.

Siehe auch