Udostępnij za pośrednictwem


Jak utworzyć niestandardowe zdarzenie kierowane (WPF .NET)

Deweloperzy aplikacji i autorzy składników Windows Presentation Foundation (WPF) mogą tworzyć niestandardowe zdarzenia kierowane w celu rozszerzania funkcjonalności zdarzeń środowiska uruchomieniowego CLR. Aby uzyskać informacje na temat możliwości zdarzeń trasowanych, zobacz Dlaczego warto używać zdarzeń trasowanych. W tym artykule opisano podstawy tworzenia niestandardowego zdarzenia routingu.

Warunki wstępne

Artykuł zakłada podstawową znajomość zdarzeń trasowanych, przy czym należy zapoznać się z Przegląd zdarzeń trasowanych. Aby postępować zgodnie z przykładami w tym artykule, warto zapoznać się z językiem Extensible Application Markup Language (XAML) i wiedzieć, jak pisać aplikacje programu Windows Presentation Foundation (WPF).

Kroki zdarzenia kierowanego

Podstawowe kroki tworzenia zdarzenia kierowanego to:

  1. Zarejestruj RoutedEvent przy użyciu metody RegisterRoutedEvent.

  2. Wywołanie rejestracji zwraca wystąpienie RoutedEvent, znane jako identyfikator zdarzenia kierowanego. Przechowuje ono zarejestrowaną nazwę zdarzenia, strategię routingui inne szczegóły zdarzenia. Przypisz identyfikator do statycznego pola tylko do odczytu. Zgodnie z konwencją:

    • Identyfikator zdarzenia kierowanego ze strategią nosi nazwę . Jeśli na przykład nazwa zdarzenia to Tap identyfikator powinien mieć nazwę TapEvent.
    • Identyfikator dla zdarzenia z trasowaniem ze strategią tunelowania nosi nazwę Preview<event name>Event. Jeśli na przykład nazwa zdarzenia to Tap identyfikator powinien mieć nazwę PreviewTapEvent.
  3. Zdefiniuj akcesory dostępu do zdarzeń CLR dla , dodaj i , usuń. Bez metod obsługi zdarzeń CLR można dodawać lub usuwać programy obsługi zdarzeń tylko za pomocą wywołań bezpośrednich do metod UIElement.AddHandler i UIElement.RemoveHandler. Dzięki akcesorom zdarzeń CLR możesz zastosować następujące mechanizmy przypisywania obsługi zdarzeń:

    • W przypadku rozszerzalnego języka znaczników aplikacji (XAML) można użyć składni atrybutów, aby dodać programy obsługi zdarzeń.
    • W języku C# można użyć operatorów += i -=, aby dodawać lub usuwać programy obsługi zdarzeń.
    • W przypadku języka VB można użyć instrukcji AddHandler i RemoveHandler, aby dodawać lub usuwać programy obsługi zdarzeń.
  4. Dodaj niestandardową logikę do wyzwalania zdarzenia kierowanego. Na przykład logika może wyzwolić zdarzenie na podstawie danych wejściowych użytkownika i stanu aplikacji.

Przykład

Poniższy przykład implementuje klasę CustomButton w niestandardowej bibliotece kontrolek. Klasa CustomButton, która pochodzi z Button:

  1. Rejestruje RoutedEvent o nazwie ConditionalClick przy użyciu metody RegisterRoutedEvent i określa strategię podczas rejestracji.
  2. Przypisuje wystąpienie RoutedEvent zwrócone z wywołania rejestracji do statycznego pola tylko do odczytu o nazwie ConditionalClickEvent.
  3. Definiuje akcesory zdarzeń dodawania i usuwania dla CLR dodać i usunąć.
  4. Dodaje niestandardową logikę, aby wywołać niestandardowe zdarzenie kierowane, gdy CustomButton jest kliknięty i spełniony jest warunek zewnętrzny. Mimo że przykładowy kod zgłasza zdarzenie kierowane ConditionalClick w ramach nadpisanej metody wirtualnej OnClick, możesz zgłosić zdarzenie w dowolny sposób.
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

Przykład zawiera oddzielną aplikację WPF, która używa znaczników XAML w celu dodania wystąpienia CustomButton do StackPaneli przypisania metody Handler_ConditionalClick jako procedury obsługi zdarzeń ConditionalClick dla elementów CustomButton i 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>

W pliku code-behind aplikacja WPF definiuje metodę obsługi zdarzenia Handler_ConditionalClick. Metody obsługi zdarzeń można zaimplementować tylko w code-behind.

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

Po kliknięciu CustomButton:

  1. Zdarzenie kierowane ConditionalClick jest wyzwalane w CustomButton.
  2. Program obsługi zdarzeń Handler_ConditionalClick dołączony do CustomButton zostaje wyzwolony.
  3. Zdarzenie kierowane ConditionalClick wędruje w górę drzewa elementów do StackPanel1.
  4. Zostanie wyzwolony program obsługi zdarzeń Handler_ConditionalClick dołączony do StackPanel1.
  5. Zdarzenie kierowane ConditionalClick przemieszcza się w górę drzewa elementów, potencjalnie wyzwalając inne procedury obsługi zdarzeń ConditionalClick dołączone do innych napotkanych elementów.

Program obsługi zdarzeń Handler_ConditionalClick uzyskuje następujące informacje o zdarzeniu, które go wyzwoliło:

  • Obiekt nadawcy , do którego jest dołączony program obsługi zdarzeń. sender zostanie CustomButton przy pierwszym uruchomieniu obsługi, a StackPanel1 przy drugim.
  • Obiekt RoutedEventArgs.Source, będący elementem, który pierwotnie zgłosił zdarzenie. W tym przykładzie Source jest zawsze CustomButton.

Uwaga

Kluczową różnicą między zdarzeniem kierowanym a zdarzeniem CLR jest to, że zdarzenie kierowane przechodzi przez drzewo elementów, szukając procedur obsługi, podczas gdy zdarzenie CLR nie przechodzi przez drzewo elementów i programy obsługi mogą dołączać tylko do obiektu źródłowego, który wywołał zdarzenie. W związku z tym zdarzenie sender kierowane trasą może być dowolnym elementem przechodzonym w drzewie elementów.

Możesz utworzyć zdarzenie tunelowania w taki sam sposób jak zdarzenie bubbling, z wyjątkiem ustawiania strategii routingu w wywołaniu rejestracji zdarzeń na Tunnel. Aby uzyskać więcej informacji na temat zdarzeń tunelowania, zobacz zdarzenia wejściowe WPF.

Zobacz też