Condividi tramite


Come creare un evento indirizzato personalizzato (WPF .NET)

Gli sviluppatori di applicazioni e gli autori di componenti di Windows Presentation Foundation (WPF) possono creare eventi indirizzati personalizzati per estendere la funzionalità degli eventi CLR (Common Language Runtime). Per informazioni sulle funzionalità degli eventi indirizzati, vedere Perché usare gli eventi indirizzati. Questo articolo illustra le nozioni di base per la creazione di un evento indirizzato personalizzato.

Prerequisiti

L'articolo presuppone una conoscenza di base degli eventi indirizzati e che sia stata letta panoramica degli eventi indirizzati. Per seguire gli esempi in questo articolo, è utile se si ha familiarità con Extensible Application Markup Language (XAML) e si sa come scrivere applicazioni Windows Presentation Foundation (WPF).

Passaggi dell'evento indirizzato

I passaggi di base per creare un evento indirizzato sono:

  1. Registrare un RoutedEvent usando il metodo RegisterRoutedEvent.

  2. La chiamata di registrazione restituisce un'istanza di RoutedEvent, nota come identificatore di evento instradato, che contiene il nome dell'evento registrato, la strategia di routing ,e altri dettagli dell'evento. Assegnare l'identificatore a un campo statico di sola lettura. Per convenzione:

    • L'identificatore di un evento indirizzato con una strategia bubbling è denominato <event name>Event. Ad esempio, se il nome dell'evento è Tap, l'identificatore deve essere denominato TapEvent.
    • L'identificatore di un evento indirizzato che utilizza la strategia di tunneling è denominato Preview<event name>Event. Ad esempio, se il nome dell'evento è Tap, l'identificatore deve essere denominato PreviewTapEvent.
  3. Definire clr aggiungere e rimuovere funzioni di accesso agli eventi. Senza le funzioni di accesso agli eventi CLR, sarà possibile aggiungere o rimuovere gestori eventi solo tramite chiamate dirette ai metodi UIElement.AddHandler e UIElement.RemoveHandler. Con le funzioni di accesso agli eventi CLR, si ottengono questi meccanismi di assegnazione del gestore eventi:

    • Per Extensible Application Markup Language (XAML), puoi usare la sintassi degli attributi per aggiungere gestori eventi.
    • Per C#, è possibile usare gli operatori += e -= per aggiungere o rimuovere gestori eventi.
    • Per VB, è possibile usare le istruzioni AddHandler e RemoveHandler per aggiungere o rimuovere gestori eventi.
  4. Aggiungere logica personalizzata per attivare l'evento indirizzato. Ad esempio, la logica potrebbe attivare l'evento in base all'input utente e allo stato dell'applicazione.

Esempio

Nell'esempio seguente viene implementata la classe CustomButton in una libreria di controlli personalizzata. Classe CustomButton, che deriva da Button:

  1. Registra un RoutedEvent denominato ConditionalClick usando il metodo RegisterRoutedEvent e specifica la strategia di propagazione durante la registrazione.
  2. Assegna l'istanza di RoutedEvent restituita dalla chiamata di registrazione a un campo statico di sola lettura denominato ConditionalClickEvent.
  3. Definisce clr aggiungere e rimuovere funzioni di accesso agli eventi.
  4. Aggiunge una logica specifica per generare l'evento indirizzato personalizzato quando si fa clic sul CustomButton e quando viene applicata una condizione esterna. Anche se il codice di esempio genera l'evento indirizzato ConditionalClick dall'interno del metodo virtuale sottoposto a override OnClick, è possibile generare l'evento in qualsiasi modo scelto.
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

L'esempio include un'applicazione WPF separata che usa il markup XAML per aggiungere un'istanza del CustomButton a un StackPanele per assegnare il metodo Handler_ConditionalClick come gestore eventi ConditionalClick per gli elementi CustomButton e 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>

Nel code-behind l'applicazione WPF definisce il metodo del gestore eventi Handler_ConditionalClick. I metodi del gestore eventi possono essere implementati solo nel 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.

Quando si fa clic su CustomButton:

  1. L'evento indirizzato ConditionalClick viene generato in CustomButton.
  2. Viene attivato il gestore eventi Handler_ConditionalClick associato a CustomButton.
  3. L'evento indirizzato ConditionalClick attraversa l'albero degli elementi fino a StackPanel1.
  4. Viene attivato il gestore eventi Handler_ConditionalClick associato a StackPanel1.
  5. L'evento instradato ConditionalClick continua a salire lungo l'albero degli elementi, potenzialmente innescando altri gestori eventi ConditionalClick collegati ad altri elementi attraversati.

Il gestore eventi Handler_ConditionalClick ottiene le informazioni seguenti sull'evento che lo ha attivato:

  • L'oggetto mittente , che è l'elemento a cui è associato il gestore eventi. Il valore di sender sarà CustomButton la prima volta che il gestore viene eseguito, e StackPanel1 la seconda volta.
  • Oggetto RoutedEventArgs.Source, ovvero l'elemento che ha originariamente generato l'evento. In questo esempio il Source è sempre CustomButton.

Nota

Una differenza fondamentale tra un evento indirizzato e un evento CLR consiste nel fatto che un evento indirizzato attraversa l'albero degli elementi, cercando gestori, mentre un evento CLR non attraversa l'albero degli elementi e i gestori possono essere collegati solo all'oggetto di origine che ha generato l'evento. Di conseguenza, un evento indirizzato sender può essere qualsiasi elemento attraversato nell'albero degli elementi.

È possibile creare un evento di tunneling allo stesso modo di un evento di bubbling, tranne che imposterai la strategia di routing nella chiamata di registrazione degli eventi su Tunnel. Per ulteriori informazioni sugli eventi di tunneling, consultare gli eventi di input di WPF .

Vedere anche