Sdílet prostřednictvím


Vytvoření vlastní směrované události (WPF .NET)

Vývojáři aplikací WPF (Windows Presentation Foundation) a autoři komponent můžou vytvářet vlastní směrované události, které rozšiřují funkce událostí modulu CLR (Common Language Runtime). Informace o možnostech směrovaných událostí najdete v tématu Proč používat směrované události. Tento článek popisuje základy vytváření vlastní směrované události.

Důležité

Dokumentace k desktopové příručce pro .NET 7 a .NET 6 se právě připravuje.

Předpoklady

V článku se předpokládá základní znalost směrovaných událostí a že jste si přečetli přehled směrovaných událostí. Pokud chcete postupovat podle příkladů v tomto článku, pomůže vám to, pokud znáte jazyk XAML (Extensible Application Markup Language) a víte, jak psát aplikace WINDOWS Presentation Foundation (WPF).

Směrované kroky událostí

Základní kroky vytvoření směrované události jsou:

  1. Zaregistrujte metodu RoutedEventRegisterRoutedEvent pomocí metody.

  2. Volání registrace vrátí RoutedEvent instanci označovanou jako identifikátor směrované události, která obsahuje registrovaný název události, strategii směrování a další podrobnosti události. Přiřaďte identifikátor statickému poli jen pro čtení. Podle konvence:

    • Identifikátor směrované události s bublinovou strategií má název <event name>Event. Pokud je Tap například název události, měl by být identifikátor pojmenován TapEvent.
    • Identifikátor směrované události se strategií tunelování má název Preview<event name>Event. Pokud je Tap například název události, měl by být identifikátor pojmenován PreviewTapEvent.
  3. Definujte přidání a odebrání přístupových objektů událostí CLR. Bez přístupových objektů událostí CLR budete moct přidávat nebo odebírat obslužné rutiny událostí pouze prostřednictvím přímých volání metod UIElement.AddHandler a UIElement.RemoveHandler metod. U přístupových objektů událostí CLR získáte tyto mechanismy přiřazení obslužné rutiny událostí:

    • Pro jazyk XAML (Extensible Application Markup Language) můžete pomocí syntaxe atributů přidat obslužné rutiny událostí.
    • V jazyce C# můžete pomocí += operátorů -= přidat nebo odebrat obslužné rutiny událostí.
    • Pro VB můžete k přidání nebo odebrání obslužných rutin událostí použít příkazy AddHandler a RemoveHandler .
  4. Přidejte vlastní logiku pro aktivaci směrované události. Logika může například aktivovat událost na základě uživatelského vstupu a stavu aplikace.

Příklad

Následující příklad implementuje CustomButton třídu v knihovně vlastních ovládacích prvků. Třída CustomButton , která je odvozena z Button:

  1. Zaregistruje pojmenovanou ConditionalClickRoutedEvent metodu RegisterRoutedEvent a během registrace určuje strategii bublání.
  2. RoutedEvent Přiřadí instanci vrácenou z volání registrace statickému poli jen pro čtení s názvem ConditionalClickEvent.
  3. Definuje přidání a odebrání přístupových objektů událostí CLR.
  4. Přidá vlastní logiku pro vyvolání vlastní směrované události při CustomButton kliknutí a použije se externí podmínka. I když ukázkový kód vyvolá ConditionalClick směrovanou událost z přepsané OnClick virtuální metody, můžete vyvolat událost libovolným způsobem, který zvolíte.
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

Příklad obsahuje samostatnou aplikaci WPF, která používá kód XAML k přidání instance objektu CustomButton do objektu StackPanela přiřadit metodu Handler_ConditionalClick jako obslužnou rutinu ConditionalClick události pro prvky CustomButton a StackPanel1 prvky.

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

V kódu na pozadí aplikace WPF definuje metodu Handler_ConditionalClick obslužné rutiny události. Metody obslužné rutiny událostí lze implementovat pouze v kódu.

// 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 kliknutí na:

  1. Směrovaná ConditionalClick událost je vyvolána na CustomButton.
  2. Aktivuje se obslužná rutina Handler_ConditionalClick události připojená k CustomButton události.
  3. Směrovaná ConditionalClick událost prochází stromem elementu do StackPanel1.
  4. Aktivuje se obslužná rutina Handler_ConditionalClick události připojená k StackPanel1 události.
  5. Směrovaná ConditionalClick událost pokračuje ve stromu elementů, který potenciálně aktivuje další ConditionalClick obslužné rutiny událostí připojené k jiným procházeným prvkům.

Obslužná Handler_ConditionalClick rutina události získá následující informace o události, která ji aktivovala:

  • Objekt odesílatele , což je prvek, ke kterému je připojena obslužná rutina události. CustomButton Bude sender prvním spuštěním obslužné rutiny a StackPanel1 druhým časem.
  • Objekt RoutedEventArgs.Source , což je prvek, který původně vyvolal událost. V tomto příkladu Source je vždy CustomButton.

Poznámka:

Klíčovým rozdílem mezi směrovanou událostí a událostí CLR je to, že směrovaná událost prochází strom prvků, hledá obslužné rutiny, zatímco událost CLR neprochází stromem elementu a obslužné rutiny se můžou připojit pouze ke zdrojovému objektu, který vyvolal událost. V důsledku toho může být směrovaná událost sender libovolným procházeným prvkem ve stromu elementů.

Událost tunelování můžete vytvořit stejným způsobem jako událost bublání, s výjimkou toho, že v volání Tunnelregistrace události nastavíte strategii směrování . Další informace o událostech tunelování najdete v tématu Události vstupu WPF.

Viz také