Jak utworzyć niestandardowe zdarzenie kierowane (WPF .NET)
Windows Presentation Foundation (WPF) deweloperzy aplikacji i autorzy składników mogą tworzyć niestandardowe zdarzenia kierowane w celu rozszerzenia funkcjonalności zdarzeń środowiska uruchomieniowego języka wspólnego (CLR). Aby uzyskać informacje na temat możliwości zdarzenia kierowanego, zobacz Why use routed events (Dlaczego używać zdarzeń kierowanych). W tym artykule opisano podstawy tworzenia niestandardowego zdarzenia kierowanego.
Ważne
Dokumentacja przewodnika po pulpicie dla platform .NET 6 i .NET 5 (w tym .NET Core 3.1) jest w trakcie budowy.
Wymagania wstępne
W tym artykule przyjęto założenie, że masz podstawową wiedzę na temat zdarzeń kierowanych i zapoznasz się z omówieniem 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 Windows Presentation Foundation (WPF).
Kroki zdarzenia kierowanego
Podstawowe kroki tworzenia zdarzenia kierowanego to:
Zarejestruj przy RoutedEvent użyciu RegisterRoutedEvent metody .
Wywołanie rejestracji zwraca wystąpienie znane jako identyfikator zdarzenia kierowanego, który przechowuje zarejestrowaną
RoutedEventnazwę zdarzenia, strategię routingu i inne szczegóły zdarzenia. Przypisz identyfikator do pola odczytu statycznego. Zgodnie z konwencją:- Identyfikator zdarzenia kierowanego ze strategią bubbling nosi nazwę
<event name>Event. Jeśli na przykład nazwa zdarzenia toTapidentyfikator powinien mieć nazwęTapEvent. - Identyfikator zdarzenia kierowanego ze strategią tunelowania nosi nazwę
Preview<event name>Event. Jeśli na przykład nazwa zdarzenia toTapidentyfikator powinien mieć nazwęPreviewTapEvent.
- Identyfikator zdarzenia kierowanego ze strategią bubbling nosi nazwę
Zdefiniuj metody dostępu do zdarzeń clR i usuń je. Bez akcesorów zdarzeń CLR można dodawać lub usuwać programy obsługi zdarzeń tylko za pomocą wywołań bezpośrednich do UIElement.AddHandler metod i UIElement.RemoveHandler . Dzięki akcesorom zdarzeń CLR uzyskasz następujące mechanizmy przypisywania procedury obsługi zdarzeń:
- W przypadku języka XAML (Extensible Application Markup Language) można użyć składni atrybutów do dodawania programów obsługi zdarzeń.
- W języku C#można użyć
+=operatorów i-=do dodawania lub usuwania procedur obsługi zdarzeń. - W przypadku języka VB można użyć instrukcji AddHandler i RemoveHandler , aby dodać lub usunąć programy obsługi zdarzeń.
Dodaj niestandardową logikę wyzwalania zdarzenia kierowanego. Na przykład logika może wyzwolić zdarzenie na podstawie stanu danych wejściowych użytkownika i aplikacji.
Przykład
Poniższy przykład implementuje klasę CustomButton w niestandardowej bibliotece kontrolek. Klasa CustomButton , która pochodzi z klasy Button:
- RoutedEvent Rejestruje nazwę przy
ConditionalClickużyciu RegisterRoutedEvent metody i określa strategię bubbling podczas rejestracji. RoutedEventPrzypisuje wystąpienie zwrócone z wywołania rejestracji do statycznego pola readonly o nazwieConditionalClickEvent.- Definiuje dodawanie i usuwanie akcesorów zdarzeń clR.
- Dodaje logikę niestandardową w celu podniesienia niestandardowego zdarzenia kierowanego po
CustomButtonkliknięciu elementu , a warunek zewnętrzny ma zastosowanie. Mimo że przykładowy kod zgłaszaConditionalClickzdarzenie kierowane z metody wirtualnej przesłoniętejOnClick, 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 obejmuje oddzielną aplikację WPF, która używa znaczników XAML w celu dodania wystąpienia CustomButton elementu do klasy StackPanel, oraz przypisania Handler_ConditionalClick metody jako ConditionalClick procedury obsługi zdarzeń dla CustomButton elementów 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 kodzie aplikacja WPF definiuje metodę obsługi zdarzeń Handler_ConditionalClick . Metody obsługi zdarzeń można zaimplementować tylko w kodzie za pomocą kodu.
// 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 CustomButton kliknięciu:
- Zdarzenie
ConditionalClickkierowane jest wywoływane w systemieCustomButton. - Procedura
Handler_ConditionalClickobsługi zdarzeń dołączona doCustomButtonprogramu jest wyzwalana. - Zdarzenie
ConditionalClickkierowane przechodzi w górę drzewa elementów doStackPanel1. - Procedura
Handler_ConditionalClickobsługi zdarzeń dołączona doStackPanel1programu jest wyzwalana. - Zdarzenie
ConditionalClickkierowane kontynuuje drzewo elementów potencjalnie wyzwalając inneConditionalClickprogramy obsługi zdarzeń dołączone do innych elementów przechodzenia.
Procedura Handler_ConditionalClick obsługi zdarzeń uzyskuje następujące informacje o zdarzeniu, które go wyzwoliło:
- Obiekt nadawcy , do którego jest dołączony program obsługi zdarzeń. Będzie
senderto pierwszy raz, gdy program obsługi zostanieCustomButtonuruchomiony, aStackPanel1drugi raz. - RoutedEventArgs.Source Obiekt, który jest elementem, który pierwotnie wzbudził zdarzenie. W tym przykładzie wartość
Sourceto zawszeCustomButton.
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 podniósł zdarzenie. W rezultacie zdarzenie sender kierowane może być dowolnym elementem przechodzenia w drzewie elementów.
Możesz utworzyć zdarzenie tunelowania w taki sam sposób jak zdarzenie bubbling, z wyjątkiem ustawisz strategię routingu w wywołaniu rejestracji zdarzeń na Tunnel. Aby uzyskać więcej informacji na temat zdarzeń tunelowania, zobacz Zdarzenia wejściowe WPF.