Omówienie dołączonych zdarzeń (WPF .NET)

Extensible Application Markup Language (XAML) definiuje składnik języka i typ zdarzenia nazywany dołączonym zdarzeniem. Dołączone zdarzenia mogą służyć do definiowania nowego zdarzenia kierowanego w klasie innej niż element i zgłaszać to zdarzenie na dowolnym elemenie w drzewie. W tym celu należy zarejestrować dołączone zdarzenie jako zdarzenie kierowane i podać określony kod zapasowy, który obsługuje dołączone funkcje zdarzeń. Ponieważ dołączone zdarzenia są rejestrowane jako zdarzenia kierowane, po wywołaniu elementu są propagowane przez drzewo elementów.

Ważne

Dokumentacja przewodnika dla komputerów dla platform .NET 7 i .NET 6 jest w budowie.

Wymagania wstępne

W tym artykule przyjęto założenie, że masz podstawową wiedzę na temat kierowanych zdarzeń programu Windows Presentation Foundation (WPF) i zapoznasz się z omówieniem zdarzeń routed i XAML w WPF. Aby postępować zgodnie z przykładami w tym artykule, warto zapoznać się z językiem XAML i wiedzieć, jak pisać aplikacje WPF.

Dołączona składnia zdarzenia

W składni XAML dołączone zdarzenie jest określane przez jego nazwę zdarzenia i jego typ właściciela w postaci <owner type>.<event name>. Ponieważ nazwa zdarzenia jest kwalifikowana przy użyciu nazwy jego typu właściciela, składnia umożliwia dołączanie zdarzenia do dowolnego elementu, który można utworzyć. Ta składnia ma również zastosowanie do procedur obsługi regularnych zdarzeń kierowanych, które dołączają do dowolnego elementu wzdłuż trasy zdarzeń.

Następująca składnia atrybutów XAML dołącza procedurę AquariumFilter_Clean obsługi dla dołączonego AquariumFilter.Clean zdarzenia do aquarium1 elementu:

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

W tym przykładzie aqua: prefiks jest niezbędny, ponieważ AquariumFilter klasy i Aquarium istnieją w innej przestrzeni nazw środowiska uruchomieniowego języka wspólnego (CLR) i zestawie.

Możesz również dołączyć programy obsługi dla dołączonych zdarzeń w kodzie. W tym celu wywołaj metodę AddHandler w obiekcie, do którego powinien zostać dołączony program obsługi, i przekaż identyfikator zdarzenia i procedurę obsługi jako parametry do metody .

Jak WPF implementuje dołączone zdarzenia

Zdarzenia dołączone do platformy WPF są implementowane jako zdarzenia kierowane wspierane przez RoutedEvent pole. W związku z tym dołączone zdarzenia są propagowane przez drzewo elementów po ich wywołaniu. Ogólnie rzecz biorąc, obiekt, który zgłasza dołączone zdarzenie, znane jako źródło zdarzeń, jest systemem lub źródłem usługi. Źródła systemu lub usługi nie są bezpośrednią częścią drzewa elementów. W przypadku innych dołączonych zdarzeń źródło zdarzeń może być elementem w drzewie, takim jak składnik w kontrolce złożonej.

Dołączone scenariusze zdarzeń

W WPF dołączone zdarzenia są używane w niektórych obszarach funkcji, w których istnieje abstrakcja na poziomie usługi. Na przykład WPF korzysta z dołączonych zdarzeń, które są włączone przez klasy statyczne Mouse lub Validation . Klasy, które wchodzą w interakcję z usługą lub korzystają z niej, mogą wchodzić w interakcje ze zdarzeniem przy użyciu dołączonej składni zdarzeń lub udostępniać dołączone zdarzenie jako zdarzenie kierowane. Ta ostatnia opcja jest częścią sposobu, w jaki klasa może zintegrować możliwości usługi.

System wejściowy WPF intensywnie używa dołączonych zdarzeń. Jednak prawie wszystkie dołączone zdarzenia są udostępniane jako równoważne nieprzyłączone zdarzenia kierowane przez elementy podstawowe. Każde zdarzenie wejściowe kierowane jest elementem członkowskim klasy elementu podstawowego i jest obsługiwane za pomocą zdarzenia CLR "otoka". Rzadko będziesz używać dołączonych zdarzeń lub obsługiwać je bezpośrednio. Na przykład łatwiej jest obsłużyć bazowe dołączone Mouse.MouseDown zdarzenie za UIElement pośrednictwem równoważnego UIElement.MouseDown zdarzenia kierowanego niż przy użyciu dołączonej składni zdarzeń w języku XAML lub kod-behind.

Dołączone zdarzenia służą celowi architektury, umożliwiając przyszłe rozszerzanie urządzeń wejściowych. Na przykład nowe urządzenie wejściowe będzie musiało podnieść Mouse.MouseDown tylko w celu symulowania danych wejściowych myszy i nie trzeba z niego korzystać Mouse . Ten scenariusz obejmuje obsługę kodu zdarzenia, ponieważ obsługa kodu XAML dołączonego zdarzenia nie byłaby odpowiednia.

Obsługa dołączonego zdarzenia

Proces kodowania i obsługi dołączonego zdarzenia jest zasadniczo taki sam jak w przypadku zdarzenia nieprzyłączonego kierowanego.

Jak wspomniano wcześniej, istniejące zdarzenia dołączone do platformy WPF zwykle nie mają być obsługiwane bezpośrednio w WPF. Częściej celem dołączonego zdarzenia jest włączenie elementu w kontrolce złożonej w celu raportowania jego stanu do elementu nadrzędnego w kontrolce. W tym scenariuszu zdarzenie jest wywoływane w kodzie i opiera się na obsłudze klas w odpowiedniej klasie nadrzędnej. Na przykład oczekuje się, że elementy w obiekcie Selector będą zgłaszać Selected dołączone zdarzenie, które jest następnie klasą obsługiwaną przez klasę Selector . Klasa Selector potencjalnie konwertuje Selected zdarzenie na SelectionChanged zdarzenie kierowane. Aby uzyskać więcej informacji na temat kierowanych zdarzeń i obsługi klas, zobacz Oznaczanie zdarzeń trasowanych jako obsługiwane i obsługa klas.

Definiowanie zdarzenia dołączonego niestandardowego

Jeśli pochodzisz z typowych klas bazowych WPF, możesz zaimplementować niestandardowe dołączone zdarzenie, dołączając dwie metody dostępu w klasie. Te metody to:

  • Metoda obsługi dodaj<nazwę>zdarzenia z pierwszym parametrem, który jest elementem, na którym jest dołączony program obsługi zdarzeń, a drugi parametr, który ma zostać dodany przez program obsługi zdarzeń. Metoda musi mieć public wartość i static, bez wartości zwracanej. Metoda wywołuje metodę klasy bazowej AddHandler , przekazując zdarzenie trasowane i procedurę obsługi jako argumenty. Ta metoda obsługuje składnię atrybutów XAML na potrzeby dołączania procedury obsługi zdarzeń do elementu. Ta metoda umożliwia również dostęp kodu do magazynu obsługi zdarzeń dla dołączonego zdarzenia.

  • Metoda obsługi usuń<nazwę>zdarzenia z pierwszym parametrem, który jest elementem, na którym jest dołączony program obsługi zdarzeń, a drugi parametr, który jest procedurą obsługi zdarzeń do usunięcia. Metoda musi mieć public wartość i static, bez wartości zwracanej. Metoda wywołuje metodę klasy bazowej RemoveHandler , przekazując zdarzenie trasowane i procedurę obsługi jako argumenty. Ta metoda umożliwia dostęp kodu do magazynu obsługi zdarzeń dla dołączonego zdarzenia.

WPF implementuje dołączone zdarzenia jako zdarzenia kierowane, ponieważ identyfikator elementu RoutedEvent jest zdefiniowany przez system zdarzeń WPF. Ponadto routing zdarzenia jest naturalnym rozszerzeniem koncepcji na poziomie języka XAML dołączonego zdarzenia. Ta strategia implementacji ogranicza obsługę dołączonych zdarzeń do UIElement klas pochodnych lub ContentElement klas pochodnych, ponieważ tylko te klasy mają AddHandler implementacje.

Na przykład poniższy kod definiuje Clean dołączone zdarzenie w AquariumFilter klasie owner, która nie jest klasą elementu. Kod definiuje dołączone zdarzenie jako zdarzenie kierowane i implementuje wymagane metody dostępu.

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

Metoda zwracająca RegisterRoutedEvent dołączony identyfikator zdarzenia jest tą samą metodą używaną do rejestrowania nieprzyłączonych zdarzeń trasowanych. Zarówno dołączone, jak i nieprzyłączone zdarzenia są rejestrowane w scentralizowanym magazynie wewnętrznym. Ta implementacja magazynu zdarzeń umożliwia pojęcie "zdarzenia jako interfejs", które zostało omówione w omówieniu zdarzeń trasowanych.

W przeciwieństwie do zdarzenia CLR "otoka" używana do tworzenia kopii zapasowych zdarzeń nieprzyłączonych trasowanych, dołączone metody dostępu zdarzeń można zaimplementować w klasach, które nie pochodzą z UIElement lub ContentElement. Jest to możliwe, ponieważ dołączony kod kopii zapasowej zdarzenia wywołuje UIElement.AddHandler metody i UIElement.RemoveHandler w przekazanym UIElement wystąpieniu. Z kolei otoka CLR dla nieprzyłączonych zdarzeń trasowanych wywołuje te metody bezpośrednio w klasie będącej właścicielem, aby klasa mogła pochodzić z UIElementklasy .

Wywoływanie zdarzenia dołączonego do platformy WPF

Proces zgłaszania dołączonego zdarzenia jest zasadniczo taki sam jak w przypadku zdarzenia nieprzyłączonego trasowanego.

Zazwyczaj kod nie będzie musiał zgłaszać żadnych istniejących zdarzeń dołączonych do platformy WPF, ponieważ te zdarzenia są zgodne z ogólnym modelem koncepcyjnym "usługi". W tym modelu klasy usług, takie jak InputManager, są odpowiedzialne za podnoszenie zdarzeń dołączonych zdefiniowanych przez platformę WPF.

Podczas definiowania zdarzenia dołączonego niestandardowego przy użyciu modelu WPF opartego na dołączonych zdarzeniach na zdarzeniach trasowanych użyj UIElement.RaiseEvent metody , aby zgłosić dołączone zdarzenie na dowolnym UIElement obiekcie lub ContentElement. Podczas wywoływanie zdarzenia kierowanego, niezależnie od tego, czy jest ono dołączone, czy nie, musisz wyznaczyć element w drzewie elementów jako źródło zdarzeń. To źródło jest następnie zgłaszane jako obiekt wywołujący RaiseEvent . Aby na przykład zgłosić AquariumFilter.Clean dołączone zdarzenie kierowane w usłudze aquarium1:

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

W poprzednim przykładzie aquarium1 jest źródłem zdarzeń.

Zobacz też