Przegląd Zdarzenia trasowane

W tym temacie opisano koncepcję zdarzeń trasowych w programie Windows Presentation Foundation (WPF) . W temacie zdefiniowano terminologię zdarzeń tras, opisano sposób przekierowywanego zdarzenia przez drzewo elementów, podsumowano sposób obsługi trasowane zdarzenia i przedstawiono sposób tworzenia własnych zdarzeń tras niestandardowych.

Wymagania wstępne

W tym temacie założono, że masz podstawową wiedzę na temat środowiska uruchomieniowego języka wspólnego (CLR) i programowania obiektowego, a także koncepcji sposobu, w jaki relacje między elementami mogą być konceptualizowane WPF jako drzewo. Aby postępować zgodnie z przykładami w tym temacie, należy również zrozumieć i wiedzieć, jak pisać bardzo Extensible Application Markup Language (XAML) WPF podstawowe aplikacje lub strony. Aby uzyskać więcej informacji, zobacz Walkthrough: My first WPF desktop application and XAML in WPF (Przewodnik: moja pierwsza aplikacja desktopowa WPF i XAML w WPF).

Co to jest zdarzenie trasowane?

Zdarzenia trasowane można myśleć z perspektywy funkcjonalności lub implementacji. W tym miejscu przedstawiono obie definicje, ponieważ niektóre osoby znajdują jedną lub drugą definicję bardziej przydatną.

Definicja funkcjonalna: Zdarzenie trasowane jest typem zdarzenia, które może wywoływać programy obsługi na wielu odbiornikach w drzewie elementów, a nie tylko na obiekcie, który wywoływał zdarzenie.

Definicja implementacji: Zdarzenie trasowane to zdarzenie CLR, które jest kopią zapasową wystąpienia klasy i jest RoutedEvent przetwarzane przez Windows Presentation Foundation (WPF) system zdarzeń.

Typowa WPF aplikacja zawiera wiele elementów. Niezależnie od tego, czy zostały utworzone w kodzie, czy zadeklarowane w elemencie , te elementy istnieją XAML w relacji drzewa elementów. Trasa zdarzenia może przechodzić w jednym z dwóch kierunkach w zależności od definicji zdarzenia, ale zazwyczaj trasa przechodzi z elementu źródłowego, a następnie "bąbelki" w górę przez drzewo elementów do momentu osiągnięcia głównego drzewa elementów (zazwyczaj strony lub okna). Ta koncepcja propagacji może być Ci znana, jeśli wcześniej pracowaliśmy z modelem obiektów DHTML.

Rozważ następujące proste drzewo elementów:

<Border Height="50" Width="300" BorderBrush="Gray" BorderThickness="1">
  <StackPanel Background="LightGray" Orientation="Horizontal" Button.Click="CommonClickHandler">
    <Button Name="YesButton" Width="Auto" >Yes</Button>
    <Button Name="NoButton" Width="Auto" >No</Button>
    <Button Name="CancelButton" Width="Auto" >Cancel</Button>
  </StackPanel>
</Border>

To drzewo elementów tworzy coś podobnego do następującego:

Przyciski Tak, Nie i Anuluj

W tym uproszczonym drzewie elementów źródłem zdarzenia jest jeden z elementów, a kliknięcie tego elementu jest pierwszym elementem, który ma możliwość obsługi Click Button Button zdarzenia. Jeśli jednak żadna procedura obsługi dołączona do elementu nie działa na zdarzenie, zdarzenie będzie bąbelkować w górę do elementu nadrzędnego w drzewie Button Button elementów, czyli StackPanel . Potencjalnie zdarzenie bąbelki do , a następnie poza element główny strony drzewa Border elementów (nie jest wyświetlany).

Innymi słowy, trasa zdarzenia dla tego Click zdarzenia jest:

Przycisk — >StackPanel-->border-->...

Scenariusze najwyższego poziomu dla zdarzeń trasowane

Poniżej przedstawiono krótkie podsumowanie scenariuszy, które wywrzeły motywację do koncepcji zdarzeń trasowanych i dlaczego typowe zdarzenie CLR nie było odpowiednie dla tych scenariuszy:

Kontrolowanie kompozycji i hermetyzacji: Różne kontrolki WPF w programie mają rozbudowany model zawartości. Na przykład możesz umieścić obraz wewnątrz , co efektywnie rozszerza Button drzewo wizualne przycisku. Jednak dodany obraz nie może przerwać zachowania testowania trafień, które powoduje, że przycisk odpowiada na element zawartości, nawet jeśli użytkownik kliknie piksele, które są technicznie częścią Click obrazu.

Punkty załącznika obsługi pojedynczej: W Windows Formularze należy wielokrotnie dołączyć tę samą obsługę w celu przetwarzania zdarzeń, które mogą być wywoływane z wielu elementów. Zdarzenia trasowane umożliwiają dołączenie tej procedury obsługi tylko raz, jak pokazano w poprzednim przykładzie, i użycie logiki procedury obsługi w celu określenia, skąd w razie potrzeby pochodzi zdarzenie. Na przykład może to być procedura obsługi dla wcześniej pokazanego polecenia XAML :

private void CommonClickHandler(object sender, RoutedEventArgs e)
{
  FrameworkElement feSource = e.Source as FrameworkElement;
  switch (feSource.Name)
  {
    case "YesButton":
      // do something here ...
      break;
    case "NoButton":
      // do something ...
      break;
    case "CancelButton":
      // do something ...
      break;
  }
  e.Handled=true;
}
Private Sub CommonClickHandler(ByVal sender As Object, ByVal e As RoutedEventArgs)
  Dim feSource As FrameworkElement = TryCast(e.Source, FrameworkElement)
  Select Case feSource.Name
    Case "YesButton"
      ' do something here ...
    Case "NoButton"
      ' do something ...
    Case "CancelButton"
      ' do something ...
  End Select
  e.Handled=True
End Sub

Obsługa klas: Zdarzenia trasowane zezwalają na statyczny program obsługi zdefiniowany przez klasę . Ta procedura obsługi klasy ma możliwość obsługi zdarzenia, zanim będzie można użyć jakichkolwiek dołączonych programów obsługi wystąpienia.

Odwoływanie się do zdarzenia bez odbicia: Niektóre techniki kodu i znaczników wymagają sposobu identyfikowania określonego zdarzenia. Zdarzenie trasowane tworzy pole jako identyfikator, co zapewnia niezawodną technikę identyfikacji zdarzeń, która nie wymaga statycznego ani RoutedEvent w czasie działania odbicia.

Jak są implementowane zdarzenia trasowane

Zdarzenie trasowane to zdarzenie CLR, które jest kopii zapasowej przez wystąpienie klasy i RoutedEvent zarejestrowane w WPF systemie zdarzeń. Wystąpienie uzyskane z rejestracji jest zwykle zachowywane jako członek pola klasy, która rejestruje i w związku z tym RoutedEvent public static readonly "jest właścicielem" kierowanego zdarzenia. Połączenie ze zdarzeniem CLR o identycznej nazwie (które jest czasami nazywane zdarzeniem "otoki") jest realizowane przez zastąpienie implementacji i dla zdarzenia add remove CLR. Zwykle wartości i są pozostawiane jako niejawna wartość domyślna, która używa odpowiedniej składni zdarzeń specyficznej dla języka do dodawania i usuwania programów obsługi add remove tego zdarzenia. Mechanizm obsługi trasowanych zdarzeń i połączenia jest koncepcyjnie podobny do właściwości zależności, która jest właściwością CLR, która jest zapasowa przez klasę i zarejestrowana w DependencyProperty WPF systemie właściwości.

W poniższym przykładzie pokazano deklarację dla niestandardowego zdarzenia trasowego, w tym rejestrację i narażenie pola identyfikatora oraz implementacje i dla Tap RoutedEvent zdarzenia add remove Tap CLR.

public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
    "Tap", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyButtonSimple));

// Provide CLR accessors for the event
public event RoutedEventHandler Tap
{
        add { AddHandler(TapEvent, value); }
        remove { RemoveHandler(TapEvent, value); }
}
Public Shared ReadOnly TapEvent As RoutedEvent = EventManager.RegisterRoutedEvent("Tap", RoutingStrategy.Bubble, GetType(RoutedEventHandler), GetType(MyButtonSimple))

' Provide CLR accessors for the event
Public Custom Event Tap As RoutedEventHandler
    AddHandler(ByVal value As RoutedEventHandler)
        Me.AddHandler(TapEvent, value)
    End AddHandler

    RemoveHandler(ByVal value As RoutedEventHandler)
        Me.RemoveHandler(TapEvent, value)
    End RemoveHandler

    RaiseEvent(ByVal sender As Object, ByVal e As RoutedEventArgs)
        Me.RaiseEvent(e)
    End RaiseEvent
End Event

Programy obsługi zdarzeń trasowane i XAML

Aby dodać program obsługi dla zdarzenia przy użyciu elementu , należy zadeklarować nazwę zdarzenia jako atrybut w XAML elemencie, który jest odbiornikiem zdarzeń. Wartość atrybutu jest nazwą zaimplementowanej metody obsługi, która musi istnieć w częściowej klasie pliku code-behind.

<Button Click="b1SetColor">button</Button>

Składnia dodawania standardowych programów obsługi zdarzeń CLR jest taka sama w przypadku dodawania trasowych programów obsługi zdarzeń, ponieważ tak naprawdę dodajesz programy obsługi do otoki zdarzeń CLR, która zawiera implementację zdarzenia kierowanego XAML poniżej. Aby uzyskać więcej informacji na temat dodawania programów obsługi zdarzeń w XAML programie , zobacz XAML w WPF.

Strategie routingu

Zdarzenia trasowane używają jednej z trzech strategii routingu:

  • Podwajanie: Wywoływane są procedury obsługi zdarzeń w źródle zdarzeń. Następnie kierowane zdarzenie kieruje do kolejnych elementów nadrzędnych do momentu osiągnięcia elementu głównego drzewa. Większość zdarzeń trasowych używa strategii rozsyłania rozsyłania. Zdarzenia trasowane są zwykle używane do zgłaszania zmian danych wejściowych lub stanu z różnych kontrolek lub innych elementów interfejsu użytkownika.

  • Bezpośrednio: Tylko sam element źródłowy ma możliwość wywoływania programów obsługi w odpowiedzi. Jest to analogiczne do "routingu" używanego przez Windows Forms dla zdarzeń. Jednak w przeciwieństwie do standardowego zdarzenia CLR, zdarzenia kierowane bezpośrednio obsługują obsługę klas (obsługa klas została wyjaśniona w nadchodzącej sekcji) i mogą być używane przez EventSetter klasy i EventTrigger .

  • Tunelowanie: Początkowo wywoływane są programy obsługi zdarzeń w katalogu głównym drzewa elementów. Następnie zdarzenie trasowane przechodzi przez kolejne elementy podrzędne wzdłuż trasy do elementu węzła, który jest źródłem zdarzenia trasowania (elementem, który wyzłożył trasowane zdarzenie). Tunelowanie trasowanych zdarzeń jest często używane lub obsługiwane w ramach składania dla kontrolki, dzięki temu zdarzenia z części złożonych mogą być celowo pomijane lub zastępowane zdarzeniami specyficznymi dla pełnej kontrolki. Zdarzenia wejściowe dostarczane w WPF programie często są implementowane jako para tunelowania/propagacji. Zdarzenia tunelowania są również czasami określane jako zdarzenia w wersji zapoznawczej ze względu na konwencję nazewnictwa używaną dla par.

Dlaczego warto używać zdarzeń trasowych?

Jako deweloper aplikacji nie zawsze musisz wiedzieć lub zadbać o to, aby zdarzenie, które jest przez Ciebie obsługi, zostało zaimplementowane jako zdarzenie trasowane. Zdarzenia trasowane mają specjalne zachowanie, ale to zachowanie jest w dużym stopniu niewidoczne, jeśli obsługa zdarzenia na elemencie, w którym jest wywoływana.

Jeśli używasz dowolnego z sugerowanych scenariuszy: definiowanie typowych programów obsługi we wspólnym katalogu głównym, składanie własnej kontrolki lub definiowanie własnej niestandardowej klasy kontrolek, staje się bardzo zaawansowane.

Odbiorniki zdarzeń trasowane i kierowane źródła zdarzeń nie muszą współużytkować wspólnego zdarzenia w hierarchii. Dowolny UIElement lub może być odbiornik zdarzeń dla dowolnego zdarzenia ContentElement trasowane. W związku z tym można użyć pełnego zestawu zdarzeń tras dostępnych w całym zestawie interfejsów API jako koncepcyjnego "interfejsu", w którym w aplikacji można wymieniać informacje o zdarzeniach. Ta koncepcja "interfejsu" dla zdarzeń trasowane jest szczególnie stosowana w przypadku zdarzeń wejściowych.

Zdarzenia trasowane mogą być również używane do komunikowania się za pośrednictwem drzewa elementów, ponieważ dane zdarzenia dla zdarzenia są utrwalane do każdego elementu w trasie. Jeden element może zmienić coś w danych zdarzenia, a ta zmiana będzie dostępna dla następnego elementu w trasie.

Poza aspektem routingu istnieją dwa inne powody, dla których dowolne zdarzenie może zostać zaimplementowane jako zdarzenie trasowane zamiast WPF standardowego zdarzenia CLR. Jeśli wdrażasz własne zdarzenia, możesz również wziąć pod uwagę następujące zasady:

  • Niektóre funkcje stylów i szablonów, takie jak i wymagają, aby przywoływał WPF EventSetter zdarzenie jako zdarzenie EventTrigger trasowane. Jest to wspomniany wcześniej scenariusz identyfikatorów zdarzeń.

  • Zdarzenia trasowane obsługują mechanizm obsługi klas, w którym klasa może określać metody statyczne, które mają możliwość obsługi zdarzeń trasowanych, zanim jakiekolwiek zarejestrowane programy obsługi wystąpień będą mieć do nich dostęp. Jest to bardzo przydatne w projekcie kontroli, ponieważ klasa może wymuszać oparte na zdarzeniach zachowania klasy, których nie można przypadkowo pominąć, obsługą zdarzenia w wystąpieniu.

Każda z powyższych kwestii jest omówiona w oddzielnej sekcji tego tematu.

Dodawanie i implementowanie programu obsługi zdarzeń dla zdarzenia trasowane

Aby dodać program obsługi zdarzeń w programie , wystarczy dodać nazwę zdarzenia do elementu jako atrybut i ustawić wartość atrybutu jako nazwę procedury obsługi zdarzeń, która implementuje odpowiedniego delegata, jak w poniższym XAML przykładzie.

<Button Click="b1SetColor">button</Button>

b1SetColor to nazwa zaimplementowanej procedury obsługi, która zawiera kod, który obsługuje Click zdarzenie. b1SetColor musi mieć taki sam podpis jak RoutedEventHandler delegat, który jest obiektem delegowanym obsługi Click zdarzeń dla zdarzenia. Pierwszy parametr wszystkich delegatów procedury obsługi zdarzeń tras określa element, do którego jest dodawany program obsługi zdarzeń, a drugi parametr określa dane dla zdarzenia.

void b1SetColor(object sender, RoutedEventArgs args)
{
  //logic to handle the Click event
}
Private Sub b1SetColor(ByVal sender As Object, ByVal args As RoutedEventArgs)
  'logic to handle the Click event
End Sub

RoutedEventHandler to podstawowy delegat procedury obsługi zdarzeń trasowany. W przypadku zdarzeń trasowych, które są wyspecjalizowane dla niektórych kontrolek lub scenariuszy, delegaci do użycia dla trasowane procedury obsługi zdarzeń również mogą stać się bardziej wyspecjalizowane, dzięki czemu mogą przesyłać wyspecjalizowane dane zdarzenia. Na przykład we wspólnym scenariuszu wejściowym można obsłużyć zdarzenie DragEnter trasowane. Procedura obsługi powinna implementować DragEventHandler delegata. Przy użyciu najbardziej konkretnego delegata można przetworzyć obiekt w programie obsługi i odczytać właściwość , która zawiera ładunek schowka DragEventArgs Data operacji przeciągania.

Aby uzyskać kompletny przykład sposobu dodawania procedury obsługi zdarzeń do elementu przy użyciu XAML polecenia , zobacz Handle a Routed Event (Obsługa zdarzenia trasowane).

Dodawanie procedury obsługi dla zdarzenia trasowane w aplikacji, która jest tworzona w kodzie, jest proste. Programy obsługi zdarzeń trasowane można zawsze dodawać za pomocą metody pomocnika (która jest taką samą metodą, jak w przypadku wywołania przez istniejącą kopię AddHandler zapasową add ). Jednak istniejące zdarzenia trasowane zwykle mają implementacje zapasowe i logikę, która umożliwia dodanie programów obsługi dla zdarzeń trasowane za pomocą składni zdarzeń specyficznej dla języka, która jest bardziej intuicyjną składnią niż metoda WPF add remove pomocnika. Poniżej przedstawiono przykład użycia metody pomocnika:

void MakeButton()
 {
     Button b2 = new Button();
     b2.AddHandler(Button.ClickEvent, new RoutedEventHandler(Onb2Click));
 }
 void Onb2Click(object sender, RoutedEventArgs e)
 {
     //logic to handle the Click event
 }
Private Sub MakeButton()
     Dim b2 As New Button()
     b2.AddHandler(Button.ClickEvent, New RoutedEventHandler(AddressOf Onb2Click))
End Sub
 Private Sub Onb2Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
     'logic to handle the Click event     
 End Sub

W następnym przykładzie pokazano składnię operatora języka C# (Visual Basic ma nieco inną składnię operatora ze względu na jej obsługę wyłuskania):

void MakeButton2()
{
  Button b2 = new Button();
  b2.Click += new RoutedEventHandler(Onb2Click2);
}
void Onb2Click2(object sender, RoutedEventArgs e)
{
  //logic to handle the Click event
}
Private Sub MakeButton2()
  Dim b2 As New Button()
  AddHandler b2.Click, AddressOf Onb2Click2
End Sub
Private Sub Onb2Click2(ByVal sender As Object, ByVal e As RoutedEventArgs)
  'logic to handle the Click event     
End Sub

Aby uzyskać przykład sposobu dodawania procedury obsługi zdarzeń do kodu, zobacz Dodawanie procedury obsługi zdarzeń przy użyciu kodu.

Jeśli używasz Visual Basic, możesz również użyć słowa kluczowego , aby dodać programy obsługi Handles jako część deklaracji procedury obsługi. Aby uzyskać więcej informacji, zobacz Visual Basic i Obsługa zdarzeń WPF.

Koncepcja obsługi

Wszystkie zdarzenia trasowane współdzielą wspólną klasę bazową danych zdarzeń, RoutedEventArgs . RoutedEventArgs Definiuje właściwość Handled , która przyjmuje wartość logiczną. Celem właściwości jest włączenie dowolnej procedury obsługi zdarzeń wzdłuż trasy w celu oznaczenia trasowane zdarzenie jako obsłużone przez ustawienie wartości Handled Handled na true . Po przetworzeniu przez program obsługi w jednym elemencie wzdłuż trasy udostępnione dane zdarzenia są ponownie raportowane do każdego odbiornika wzdłuż trasy.

Wartość ma wpływ na sposób, w jaki trasowane zdarzenie jest zgłaszane lub przetwarzane w przypadku dalszego ruchu Handled wzdłuż trasy. Jeśli element znajduje się w danych zdarzenia dla trasowane zdarzenie, programy obsługi, które nasłuchują tego zdarzenia trasowane w innych elementach, zazwyczaj nie są już wywoływane dla Handled true tego konkretnego wystąpienia zdarzenia. Dotyczy to zarówno programów obsługi dołączonych do programu , jak i dla programów obsługi dodanych za pomocą składni załączników obsługi zdarzeń specyficznych dla języka, XAML takich += jak lub Handles . W przypadku najbardziej typowych scenariuszy obsługi oznaczanie zdarzenia jako obsługiwanego przez ustawienie opcji spowoduje Handled "zatrzymanie" routingu dla trasy tunelowania lub trasy rozdysłania, a także dla dowolnego zdarzenia obsługiwanego w punkcie trasy przez program obsługi true klasy.

Istnieje jednak mechanizm "handledEventsToo", zgodnie z którym odbiorniki mogą nadal uruchamiać programy obsługi w odpowiedzi na zdarzenia trasowane, gdzie są w Handled true danych zdarzenia. Innymi słowy, trasa zdarzeń nie jest rzeczywiście zatrzymana przez oznaczenie danych zdarzenia jako obsłużone. Mechanizm handledEventsToo można używać tylko w kodzie lub w EventSetter :

Oprócz zachowania tego stanu w zdarzeniach trasowane pojęcie ma wpływ na sposób projektowania aplikacji i pisania kodu Handled Handled procedury obsługi zdarzeń. Można określić, Handled że jest to prosty protokół, który jest ujmowany przez zdarzenia trasowane. Sposób korzystania z tego protokołu należy do Ciebie, ale koncepcyjny projekt sposobu użycia wartości jest Handled następujący:

  • Jeśli zdarzenie trasowane jest oznaczone jako obsłużone, nie musi być ponownie obsługiwane przez inne elementy wzdłuż tej trasy.

  • Jeśli zdarzenie trasowane nie jest oznaczone jako obsłużone, inne odbiorniki, które były wcześniej wzdłuż trasy, wybrały opcję nie rejestrowania programu obsługi lub zarejestrowane programy obsługi nie wybrały manipulowania danymi zdarzenia i zostały ustawione na Handled true wartość . (Lub jest oczywiście możliwe, że bieżący odbiornik jest pierwszym punktem na trasie). Programy obsługi na bieżącym odbiorniku mają teraz trzy możliwe kursy akcji:

    • W ogóle nie bierz żadnych działań. zdarzenie pozostaje nieobsługiwane, a zdarzenie jest trasowane do następnego odbiornika.

    • Wykonaj kod w odpowiedzi na zdarzenie, ale ustal, że podjęte działanie nie było wystarczająco istotne, aby zagwarantować oznaczenie zdarzenia jako obsłużone. Zdarzenie kieruje do następnego odbiornika.

    • Wykonaj kod w odpowiedzi na zdarzenie. Oznacz zdarzenie jako obsługiwane w danych zdarzenia przekazanych do procedury obsługi, ponieważ podjęte działanie zostało uznane za wystarczająco istotne, aby wymagać oznaczenia jako obsłużone. Zdarzenie nadal kieruje do następnego odbiornika, ale w danych zdarzenia, więc tylko odbiorniki mają możliwość Handled = true handledEventsToo wywoływania dalszych programów obsługi.

Ten koncepcyjny projekt jest wzmacniany przez wspomniane wcześniej zachowanie routingu: dołączanie programów obsługi dla trasowanych zdarzeń, które są wywoływane, mimo że poprzednia procedura obsługi wzdłuż trasy ma już wartość Handled true .

Aby uzyskać więcej informacji na temat , obsługi klas trasowane zdarzeń i zalecenia dotyczące sytuacji, gdy należy oznaczyć trasowane zdarzenie jako , zobacz Oznaczanie zdarzeń trasowane jako obsłużone Handled Handled i Obsługa klas.

W aplikacjach dość często po prostu obsługuje się zdarzenie rozsyłane podmuchem na obiekcie, który je wywrzeł, i w ogóle nie zajmuje się charakterystykami routingu zdarzenia. Jednak nadal dobrą praktyką jest oznaczenie kierowanego zdarzenia jako obsługiwanego w danych zdarzenia, aby zapobiec nieprzewidzianym efektom ubocznym na wypadek, gdy element, który znajduje się dalej w drzewie elementów, ma również program obsługi dołączony do tego samego zdarzenia trasowania.

Programy obsługi klas

Jeśli definiujesz klasę pochodzącą w jakiś sposób z klasy , możesz również zdefiniować i dołączyć program obsługi klasy dla zdarzenia trasowane, które jest zadeklarowaną lub odziedziczzoną członkiem DependencyObject zdarzenia klasy. Programy obsługi klas są wywoływane przed dowolnymi programami obsługi odbiornika wystąpienia dołączonymi do wystąpienia tej klasy za każdym razem, gdy zdarzenie trasowane dociera do wystąpienia elementu w swojej trasie.

Niektóre WPF kontrolki mają naturalną obsługę klas dla niektórych trasowane zdarzenia. Może to spowodować, że zdarzenie trasowane nigdy nie zostanie podniesione, ale w rzeczywistości jest obsługiwane przez klasę, a trasowane zdarzenie może być nadal obsługiwane przez procedury obsługi wystąpienia, jeśli używasz określonych technik. Ponadto wiele klas bazowych i kontrolek uwidacznia metody wirtualne, których można użyć do zastąpienia zachowania obsługi klasy. Aby uzyskać więcej informacji na temat sposobu pracy z niepożądaną obsługą klas i definiowania własnej obsługi klas w klasie niestandardowej, zobacz Oznaczanie zdarzeń trasowanych jako obsłużone i Obsługa klas.

Zdarzenia dołączone w WPF

Język XAML definiuje również specjalny typ zdarzenia nazywany dołączonym zdarzeniem. Dołączone zdarzenie umożliwia dodanie programu obsługi dla określonego zdarzenia do dowolnego elementu. Element obsługi zdarzenia nie musi definiować ani dziedziczyć dołączonego zdarzenia i ani obiekt, który potencjalnie ma zdarzenie, ani docelowe wystąpienie obsługi nie musi definiować ani w inny sposób "być właścicielem" tego zdarzenia jako elementu członkowskiego klasy.

System WPF wejściowy w szerokim zastosowaniem zdarzeń dołączonych. Jednak prawie wszystkie te dołączone zdarzenia są przekazywane za pośrednictwem elementów podstawowych. Następnie zdarzenia wejściowe są wyświetlane jako równoważne nieołączona trasowane zdarzenia, które są członkami klasy elementu podstawowego. Na przykład bazowe dołączone zdarzenie można łatwiej obsłużyć na dowolnym z nich, używając polecenia na tym, zamiast zajmować się dołączaną składnią zdarzeń w Mouse.MouseDown UIElement MouseDown UIElement XAML programie lub code.

Aby uzyskać więcej informacji o zdarzeniach dołączonych w WPF programie , zobacz Przegląd zdarzeń dołączonych.

Kwalifikowane nazwy zdarzeń w XAML

Inne użycie składni, które przypomina nazwę typu. Składnia zdarzeń dołączona nazwa_zdarzenia, ale nie ściśle mówi o użyciu dołączonych zdarzeń, ma miejsce w przypadku dołączania programów obsługi dla trasowane zdarzeń, które są wywoływane przez elementy podrzędne. Procedury obsługi są dołączane do wspólnego elementu nadrzędnego, aby korzystać z routingu zdarzeń, mimo że wspólny element nadrzędny może nie mieć odpowiedniego zdarzenia trasowane jako element członkowski. Ponownie rozważmy ten przykład:

<Border Height="50" Width="300" BorderBrush="Gray" BorderThickness="1">
  <StackPanel Background="LightGray" Orientation="Horizontal" Button.Click="CommonClickHandler">
    <Button Name="YesButton" Width="Auto" >Yes</Button>
    <Button Name="NoButton" Width="Auto" >No</Button>
    <Button Name="CancelButton" Width="Auto" >Cancel</Button>
  </StackPanel>
</Border>

W tym miejscu odbiornik elementu nadrzędnego, w którym dodano program obsługi, to StackPanel . Jednak dodaje program obsługi dla zdarzenia trasowane, które zostało zadeklarowane i zostanie zgłoszone przez klasę (w rzeczywistości, ale dostępne dla za Button ButtonBase Button pośrednictwem dziedziczenia). Button "jest właścicielem" zdarzenia, ale system zdarzeń trasowany zezwala na dołączenie obsługi dowolnego przekierowego zdarzenia do dowolnego odbiornika wystąpienia, który w przeciwnym razie może dołączyć odbiorniki dla zdarzenia środowiska uruchomieniowego języka wspólnego UIElement ContentElement (CLR). Domyślna przestrzeń nazw xmlns dla tych kwalifikowanych nazw atrybutów zdarzeń jest zazwyczaj domyślną przestrzenią nazw xmlns, ale można również określić poprzedzone prefiksami przestrzenie nazw dla niestandardowych WPF zdarzeń trasowanych. Aby uzyskać więcej informacji na temat xmlns, zobacz Obszary nazw XAML i Mapowanie przestrzeni nazw dla WPF XAML.

Zdarzenia wejściowe WPF

Jedno częste stosowanie zdarzeń trasowych w ramach WPF platformy jest dla zdarzeń wejściowych. W WPF programie nazwy zdarzeń trasowanych tunelowania są poprzedzone słowem "Wersja zapoznawcza" zgodnie z konwencją. Zdarzenia wejściowe często są w parach, a jedno jest zdarzeniem propagacji, a drugie jest zdarzeniem tunelowania. Na przykład zdarzenie i zdarzenie mają taki sam podpis, przy pierwszym z nich jest zdarzeniem wejściowym podwojenia, a drugie jest zdarzeniem wejściowym KeyDown PreviewKeyDown tunelowania. Czasami zdarzenia wejściowe mają tylko wersję rozdysłania lub być może tylko wersję kierowaną bezpośrednio. W dokumentacji kierowane tematy zdarzeń odwołują się do podobnych tras zdarzeń z alternatywnymi strategiami routingu, jeśli takie zdarzenia trasowane istnieją, a sekcje na zarządzanych stronach referencyjnych wyjaśniają strategię routingu poszczególnych zdarzeń tras.

WPF Zdarzenia wejściowe, które są dostępne w parach, są implementowane w taki sposób, że pojedyncza akcja użytkownika z danych wejściowych, taka jak naciśnięcie przycisku myszy, będzie kolejno zgłaszać oba trasowane zdarzenia pary. Po pierwsze zdarzenie tunelowania jest wywoływane i przemieszcza się jego trasą. Następnie zdarzenie rozdysłania jest wywoływane i przemieszcza się jego trasą. Te dwa zdarzenia dosłownie współdzielą to samo wystąpienie danych zdarzenia, ponieważ wywołanie metody w klasie implementujące, która wywołuje zdarzenie podwajania, nasłuchuje danych zdarzenia ze zdarzenia tunelowania i ponownie używa go w nowym zdarzeniu RaiseEvent wywoływanym. Odbiorniki z programami obsługi dla zdarzenia tunelowania mają pierwszą możliwość oznaczenia obsługiwanego zdarzenia trasowania (najpierw programy obsługi klasy, a następnie programy obsługi wystąpień). Jeśli element wzdłuż trasy tunelowania oznaczył trasowane zdarzenie jako obsłużone, dane zdarzenia już obsłużone są wysyłane dla zdarzenia rozdysłania, a typowe procedury obsługi dołączone do równoważnych zdarzeń wejściowych podwojenia nie będą wywoływane. W przypadku wystąpień na zewnątrz będzie to tak, jakby obsługiwane zdarzenie podwajanie nie zostało nawet podniesione. Takie zachowanie obsługi jest przydatne w przypadku składania kontrolek, w którym wszystkie zdarzenia wejściowe oparte na trafieniu lub zdarzenia wejściowe oparte na fokusie powinny być zgłaszane przez końcową kontrolkę, a nie przez jej złożone części. Końcowy element sterowania znajduje się bliżej katalogu głównego w składaniu i dlatego ma możliwość klasy najpierw obsłużenia zdarzenia tunelowania i być może "zamienić" to przekierowane zdarzenie na zdarzenie bardziej specyficzne dla kontroli w ramach kodu, który obsługuje klasę sterowania.

Jako ilustrację sposobu działania przetwarzania zdarzeń wejściowych rozważmy następujący przykład zdarzenia wejściowego. Na poniższej ilustracji leaf element #2 drzewa element jest źródłem zarówno zdarzenia , jak i zdarzenia PreviewMouseDown MouseDown :

Diagram routingu zdarzeń

Kolejność przetwarzania zdarzeń jest następująca:

  1. PreviewMouseDown (tunel) w elemencie głównym.

  2. PreviewMouseDown (tunel) na stronie elementu pośredniego #1.

  3. PreviewMouseDown (tunel) w elemencie źródłowym #2.

  4. MouseDown (bąbelek) w elemencie źródłowym #2.

  5. MouseDown (bąbelek) na stronie elementu pośredniego #1.

  6. MouseDown (bąbelek) na elemencie głównym.

Delegat procedury obsługi zdarzeń trasowany dostarcza odwołania do dwóch obiektów: obiektu, który wywoływał zdarzenie, i obiektu, w którym wywołano program obsługi. Obiekt, w którym wywołano program obsługi, jest obiektem zgłoszonym przez sender parametr . Obiekt, w którym zdarzenie zostało po raz pierwszy zgłoszone, jest zgłaszany przez Source właściwość w danych zdarzenia. Trasowane zdarzenie nadal może być wywoływane i obsługiwane przez ten sam obiekt, w którym to przypadku i są identyczne (ma to miejsce w przypadku kroków 3 i 4 na przykładowej liście sender Source przetwarzania zdarzeń).

Z powodu tunelowania i propagacji elementy nadrzędne odbierają zdarzenia wejściowe, gdzie element Source jest jednym z ich elementów podrzędnych. Gdy ważne jest, aby wiedzieć, czym jest element źródłowy, można zidentyfikować element źródłowy, korzystając z Source właściwości .

Zwykle po oznaczzeniu zdarzenia wejściowego Handled dalsze procedury obsługi nie są wywoływane. Zazwyczaj zdarzenia wejściowe należy oznaczać jako obsługiwane zaraz po wywołaniu procedury obsługi, która dotyczy obsługi logicznej specyficznej dla aplikacji znaczenia zdarzenia wejściowego.

Wyjątkiem od tej ogólnej instrukcji dotyczącej stanu jest to, że programy obsługi zdarzeń wejściowych, które są zarejestrowane w celu celowego ignorowania stanu danych zdarzenia, nadal będą wywoływane wzdłuż Handled Handled jednej z tras. Aby uzyskać więcej informacji, zobacz Podgląd zdarzeń lub Oznaczanie trasowane zdarzeń jako obsłużone i Obsługa klas.

Model współużytkowania danych zdarzeń między zdarzeniami tunelowania i podwyższania poziomu oraz sekwencyjnego podniesienia poziomu pierwszego tunelowania, a następnie zdarzeń podwyższania poziomu, nie jest koncepcją, która zazwyczaj jest prawdziwa dla wszystkich zdarzeń tras. To zachowanie jest zaimplementowane przez sposób, w jaki urządzenia wejściowe wybierają możliwość podniesienia i WPF połączenia par zdarzeń wejściowych. Implementowanie własnych zdarzeń wejściowych jest zaawansowanym scenariuszem, ale możesz też postępować zgodnie z tym modelem dla własnych zdarzeń wejściowych.

Niektóre klasy mogą obsługiwać klasy określonych zdarzeń wejściowych, zwykle z zamiarem ponownego zdefiniowania, co oznacza określone zdarzenie wejściowe sterowane przez użytkownika w ramach tej kontrolki i podniesienia nowego zdarzenia. Aby uzyskać więcej informacji, zobacz Oznaczanie trasowane zdarzeń jako obsłużone i Obsługa klas.

Aby uzyskać więcej informacji na temat danych wejściowych oraz sposobu interakcji danych wejściowych i zdarzeń w typowych scenariuszach aplikacji, zobacz Przegląd danych wejściowych.

EventSetters i EventTriggers

W stylach można dołączyć wstępnie zadeklarowaną składnię obsługi zdarzeń do XAML znaczników przy użyciu EventSetter . Gdy styl jest stosowany, do wystąpienia w stylu jest dodawana procedura obsługi, do których istnieje odwołanie. Można zadeklarować tylko EventSetter dla zdarzenia trasowane. Poniżej przedstawiono przykład. Należy pamiętać, b1SetColor że metoda, do których odwołuje się tutaj, znajduje się w pliku code-behind.

<StackPanel
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="SDKSample.EventOvw2"
  Name="dpanel2"
  Initialized="PrimeHandledToo"
>
  <StackPanel.Resources>
    <Style TargetType="{x:Type Button}">
      <EventSetter Event="Click" Handler="b1SetColor"/>
    </Style>
  </StackPanel.Resources>
  <Button>Click me</Button>
  <Button Name="ThisButton" Click="HandleThis">
    Raise event, handle it, use handled=true handler to get it anyway.
  </Button>
</StackPanel>

Zaletą uzyskaną w tym miejscu jest to, że styl może zawierać wiele innych informacji, które można zastosować do dowolnego przycisku w aplikacji, i że element tego stylu sprzyja ponownemu używaniu kodu nawet na poziomie EventSetter na znaczników. Ponadto metoda klasy stanowi abstrakcję nazw metod obsługi o krok dalej od ogólnej aplikacji i EventSetter znaczników strony.

Inną wyspecjalizowaną składnią łączącą trasowane zdarzenia i funkcje animacji WPF jest EventTrigger . Podobnie jak w przypadku , tylko trasowane zdarzenia EventSetter mogą być używane dla EventTrigger . Zazwyczaj element jest zadeklarowany jako część stylu, ale element może być również zadeklarowany na elementach na poziomie strony jako część kolekcji lub EventTrigger EventTrigger w Triggers . ControlTemplate Element umożliwia określenie elementu uruchamianego za każdym razem, gdy zdarzenie trasowane osiągnie element w swojej trasie, który EventTrigger deklaruje element dla tego Storyboard EventTrigger zdarzenia. Zaletą działania typu over just handling the event i powodowanie uruchamiania istniejącej storyboard jest to, że element zapewnia lepszą kontrolę nad storyboardem i jego zachowaniem EventTrigger EventTrigger w czasie działania. Aby uzyskać więcej informacji, zobacz Używanie wyzwalaczy zdarzeń do kontrolowania storyboardu po jego uruchamianiu.

Więcej informacji o zdarzeniach trasowych

W tym temacie omówiono przede wszystkim zdarzenia trasowane z perspektywy opisywania podstawowych pojęć i oferowanie wskazówek dotyczących sposobu i czasu reagowania na kierowane zdarzenia, które są już obecne w różnych podstawowych elementach i kontrolkach. Można jednak utworzyć własne zdarzenie trasowane w klasie niestandardowej wraz ze wszystkimi niezbędnymi możliwościami, takimi jak wyspecjalizowane klasy danych zdarzeń i delegaty. Właściciel zdarzenia kierowanego może być dowolną klasą, ale trasowane zdarzenia muszą być wywoływane i obsługiwane przez klasy lub pochodne, aby UIElement ContentElement było przydatne. Aby uzyskać więcej informacji na temat zdarzeń niestandardowych, zobacz Create a Custom Routed Event (Tworzenie niestandardowego zdarzenia trasowego).

Zobacz też