Freigeben über


So erstellen Sie ein benutzerdefiniertes Routingereignis (WPF .NET)

Windows Presentation Foundation (WPF)-Anwendungsentwickler und Komponentenautoren können benutzerdefinierte weitergeleitete Ereignisse erstellen, um die Funktionalität der Ereignisse für allgemeine Sprachlaufzeit (CLR) zu erweitern. Informationen zu Routingereignisfunktionen finden Sie unter Warum routingfähige Ereignisse verwenden. In diesem Artikel werden die Grundlagen des Erstellens eines benutzerdefinierten Routingereignisses behandelt.

Voraussetzungen

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

Routingereignisschritte

Die grundlegenden Schritte zum Erstellen eines weitergeleiteten Ereignisses sind:

  1. Registrieren Sie ein RoutedEvent mit der RegisterRoutedEvent-Methode.

  2. Der Registrierungsaufruf gibt eine RoutedEvent Instanz zurück, die als Routingereignisbezeichner bezeichnet wird, der den Namen des registrierten Ereignisses, Routingstrategieund andere Ereignisdetails enthält. Weisen Sie den Bezeichner einem statischen schreibgeschützen Feld zu. Nach Konvention:

    • Der Bezeichner für ein Routingereignis mit einer Bubbling-Strategie wird <event name>Event benannt. Wenn der Ereignisname beispielsweise Tap ist, sollte der Bezeichner TapEventbenannt werden.
    • Der Bezeichner für ein Routingereignis mit einer Tunnel-Strategie wird Preview<event name>Event benannt. Wenn der Ereignisname beispielsweise Tap ist, sollte der Bezeichner PreviewTapEventbenannt werden.
  3. Definieren Sie Hinzufügen von CLR und Entfernen von Ereignisaccessors. Ohne CLR-Ereigniszugriffer können Sie nur Ereignishandler über direkte Aufrufe der UIElement.AddHandler- und UIElement.RemoveHandler-Methoden hinzufügen oder entfernen. Mit CLR-Ereignisaccessors erhalten Sie diese Ereignishandlerzuweisungsmechanismen:

    • Für Extensible Application Markup Language (XAML) können Sie Attributsyntax verwenden, um Ereignishandler hinzuzufügen.
    • Für C# können Sie die Operatoren += und -= verwenden, um Ereignishandler hinzuzufügen oder zu entfernen.
    • Für VB können Sie die AddHandler- und RemoveHandler--Anweisungen verwenden, um Ereignishandler hinzuzufügen oder zu entfernen.
  4. Fügen Sie benutzerdefinierte Logik hinzu, um das Routingereignis auszulösen. Ihre Logik kann z. B. das Ereignis basierend auf Benutzereingabe und Anwendungszustand auslösen.

Beispiel

Im folgenden Beispiel wird die CustomButton Klasse in einer benutzerdefinierten Steuerelementbibliothek implementiert. Die CustomButton Klasse, die von Buttonabgeleitet wird:

  1. Registriert einen RoutedEvent-Namen ConditionalClick mithilfe der Methode RegisterRoutedEvent und gibt die Bubbling-Strategie während der Registrierung an
  2. Weist die Instanz, die RoutedEvent vom Registrierungsaufruf zurückgegeben wurde, einem statischen Readonly-Feld namens ConditionalClickEvent zu.
  3. Definieren Sie CLR-Add - und Remove-Ereigniszugriffer .
  4. Fügt benutzerdefinierte Logik hinzu, um das benutzerdefinierte routed-Ereignis zu auslösen, wenn die CustomButton-Option geklickt wird und eine externe Bedingung angewendet wird. Obwohl der Beispielcode das ConditionalClick weitergeleitete Ereignis aus der überschriebenen OnClick virtuellen Methode auslöst, können Sie Ihr Ereignis auf jede Weise auslösen, die Sie auswählen.
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

Das Beispiel enthält eine separate WPF-Anwendung, die XAML-Markup verwendet, um eine Instanz des CustomButton Elements StackPanelhinzuzufügen und die Handler_ConditionalClick Methode als ConditionalClick Ereignishandler für die CustomButton elemente StackPanel1 zuzuweisen.

<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>

In Codebehind definiert die WPF-Anwendung die Handler_ConditionalClick Ereignishandlermethode. Ereignishandlermethoden können nur in Codebehind implementiert werden.

// 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.

Wenn CustomButton geklickt wurde:

  1. Das Routingereignis ConditionalClick wird auf CustomButtonausgelöst.
  2. Der Handler_ConditionalClick-Ereignishandler, der an CustomButton angehängt wurde, wird ausgelöst.
  3. Das ConditionalClick-Routingereignis durchläuft die Elementstruktur auf StackPanel1.
  4. Der Handler_ConditionalClick-Ereignishandler, der an StackPanel1 angehängt wurde, wird ausgelöst.
  5. Das ConditionalClick-Routingereignis folgt der Elementstruktur, die möglicherweise andere ConditionalClick-Ereignishandler auslösen, die an andere durchlaufene Elemente angefügt sind.

Der Handler_ConditionalClick-Ereignishandler ruft die folgenden Informationen zum Ereignis ab, das es ausgelöst hat:

  • Das Sender-Objekt, das das Element ist, an das der Ereignishandler angefügt ist sender ist CustomButton, wenn der Handler das erste Mal ausgeführt wird, und StackPanel1 das zweite Mal.
  • Das RoutedEventArgs.Source-Objekt, bei dem es sich um das Element handelt, das das Ereignis ursprünglich ausgelöst hat. In diesem Beispiel ist Source immer CustomButton.

Anmerkung

Ein wichtiger Unterschied zwischen einem routbaren Ereignis und einem CLR-Ereignis besteht darin, dass ein routbares Ereignis die Elementstruktur durchläuft und nach Handlern sucht, während ein CLR-Ereignis dies nicht tut und Handler nur an das Quellobjekt angefügt werden können, das das Ereignis ausgelöst hat. Daher kann ein Routingereignis sender jedes durchlaufene Element in der Elementstruktur sein.

Sie können ein Tunneling-Ereignis auf dieselbe Weise wie ein Bubbling-Ereignis erstellen, außer sie legen die Routingstrategie im Ereignisregistrierungsaufruf fest Tunnel. Weitere Informationen zu Tunnelereignissen finden Sie unter WPF-Eingabeereignisse.

Weitere Informationen