Cenni preliminari sugli eventi associati

Extensible Application Markup Language (XAML) definisce un componente del linguaggio e un tipo di evento chiamato evento associato. Il concetto di evento associato consente di aggiungere un gestore per un determinato evento a un elemento arbitrario, anziché a un elemento che definisce o eredita effettivamente l'evento. In questo caso, né l'oggetto che genera potenzialmente l'evento, né l'istanza di gestione di destinazione definisce o possiede in altro modo l'evento.

Prerequisiti

Questo argomento si presuppone di aver letto Cenni preliminari sugli eventi indirizzati e Cenni preliminari su XAML (WPF).

Sintassi per gli eventi associati

Gli eventi associati hanno una sintassi XAML e uno schema di codifica che deve essere usato dal codice di supporto per supportare l'utilizzo dell'evento associato.

Nella sintassi XAML, l'evento associato viene specificato non solo dal nome dell'evento, ma dal tipo proprietario più il nome dell'evento, separato da un punto (.). Dato che il nome di evento è qualificato con il nome del tipo proprietario, la sintassi dell'evento associato consente l'associazione di tale evento a qualsiasi elemento di cui è possibile creare un'istanza.

Ad esempio, di seguito è riportata la sintassi XAML per collegare un gestore per un NeedsCleaning evento associato personalizzato:

<aqua:Aquarium Name="theAquarium" Height="600" Width="800" aqua:AquariumFilter.NeedsCleaning="WashMe"/>

Si noti il prefisso aqua:, necessario in questo caso perché l'evento associato è un evento personalizzato tratto da un xmlns mappato personalizzato.

Modalità di implementazione degli eventi associati in WPF

In WPF gli eventi associati sono supportati da un RoutedEvent campo e vengono instradati attraverso la struttura ad albero dopo la generazione. In genere, l'origine dell'evento associato (oggetto che genera l'evento) è un'origine di sistema o servizio e l'oggetto che esegue il codice che genera l'evento non è pertanto parte diretta dell'albero degli elementi.

Scenari per gli eventi associati

In WPF gli eventi associati sono presenti in determinate aree di funzionalità in cui è presente un'astrazione a livello di servizio, ad esempio per gli eventi abilitati dalla Mouse classe statica o dalla Validation classe. Le classi che interagiscono con il servizio o lo usano possono usano l'evento nella sintassi dell'evento associato o scegliere di usarlo come un evento indirizzato che fa parte del modo in cui la classe integra le funzionalità del servizio.

Sebbene WPF definisca un certo numero di eventi associati, gli scenari in cui si utilizzerà o si gestirà direttamente l'evento associato sono molto limitati. In genere, l'evento associato serve a scopo di architettura, ma viene quindi inoltrato a un evento indirizzato non associato (supportato con un evento CLR "wrapper").

Ad esempio, l'evento associato sottostante Mouse.MouseDown può essere gestito in modo più semplice in qualsiasi dato UIElement usando MouseDown su, UIElement invece di gestire la sintassi degli eventi associati in XAML o nel codice. L'evento associato assolve a uno scopo nell'architettura perché consente l'espansione futura dei dispositivi di input. Per simulare l'input del mouse è necessario che il dispositivo ipotetico aumenti solo per Mouse.MouseDown simulare l'input del mouse e non è necessario derivare da Mouse a questo scopo. Tuttavia, questo scenario implica la gestione del codice degli eventi e la gestione XAML dell'evento associato non è pertinente per questo scenario.

Gestione di un evento associato in WPF

Il processo di gestione di un evento associato e il codice del gestore che verrà scritto è fondamentalmente lo stesso necessario per un evento indirizzato.

In generale, un evento associato WPF non è molto diverso da un evento indirizzato WPF. Le differenze sono il modo in cui l'evento viene originato e il modo in cui viene esposto da una classe come membro (che influiscono anche sulla sintassi del gestore XAML).

Tuttavia, come indicato in precedenza, gli eventi associati WPF esistenti non sono destinati in modo specifico alla gestione in WPF. Più spesso, lo scopo dell'evento è quello di consentire la segnalazione di uno stato da parte di un elemento composto a un elemento padre nella composizione, nel qual caso l'evento viene in genere generato nel codice e si basa inoltre sulla gestione della classe nella classe padre rilevante. Ad esempio, gli elementi all'interno di un oggetto Selector dovrebbero generare l' Selected evento associato, che è quindi una classe gestita dalla Selector classe e quindi potenzialmente convertita dalla Selector classe in un evento indirizzato diverso, SelectionChanged . Per altre informazioni sugli eventi indirizzati e sulla gestione delle classi, vedere Contrassegno degli eventi indirizzati come gestiti e gestione delle classi.

Definizione di eventi associati personalizzati come eventi indirizzati

Se si esegue la derivazione da classi base WPF comuni, è possibile implementare eventi allegati personalizzati includendo determinati metodi di modello nella classe e usando metodi di utilità già presenti nelle classi di base.

Il modello è il seguente:

  • Metodo che aggiunge il gestore EventName con due parametri. Il primo parametro è l'istanza di a cui viene aggiunto il gestore eventi. Il secondo parametro è il gestore eventi da aggiungere. Il metodo deve essere public e static , senza alcun valore restituito.

  • Metodo Remove EventName handler con due parametri. Il primo parametro è l'istanza da cui viene rimosso il gestore eventi. Il secondo parametro è il gestore eventi da rimuovere. Il metodo deve essere public e static , senza alcun valore restituito.

Il metodo della funzione di accesso del gestore Add EventName facilita l'elaborazione XAML quando gli attributi del gestore eventi associati sono dichiarati su un elemento. Anche i metodi Add EventName handler e Remove EventName handler abilitano l'accesso al codice all'archivio del gestore eventi per l'evento associato.

Questo modello generale non è ancora abbastanza preciso per l'implementazione pratica in un Framework, perché qualsiasi implementazione del reader XAML potrebbe avere schemi diversi per l'identificazione degli eventi sottostanti nel linguaggio e nell'architettura di supporto. Questo è uno dei motivi per cui WPF implementa gli eventi associati come eventi indirizzati. l'identificatore da utilizzare per un evento ( RoutedEvent ) è già definito dal sistema di eventi WPF. Inoltre, il routing di un evento è un'estensione di implementazione naturale nel concetto a livello di linguaggio XAML di un evento associato.

L'implementazione dell' aggiunta del gestore EventName per un evento associato WPF consiste nella chiamata di AddHandler con l'evento indirizzato e il gestore come argomenti.

Questa strategia di implementazione e il sistema di eventi indirizzati in generale limitano la gestione degli eventi associati a classi derivate UIElement o ContentElement classi derivate, perché solo le classi hanno AddHandler implementazioni.

Il codice seguente, ad esempio, definisce l' NeedsCleaning evento associato sulla classe Owner Aquarium , usando la strategia di eventi associati WPF per dichiarare l'evento associato come un evento indirizzato.

public static readonly RoutedEvent NeedsCleaningEvent = EventManager.RegisterRoutedEvent("NeedsCleaning", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AquariumFilter));
public static void AddNeedsCleaningHandler(DependencyObject d, RoutedEventHandler handler)
{
    UIElement uie = d as UIElement;
    if (uie != null)
    {
        uie.AddHandler(AquariumFilter.NeedsCleaningEvent, handler);
    }
}
public static void RemoveNeedsCleaningHandler(DependencyObject d, RoutedEventHandler handler)
{
    UIElement uie = d as UIElement;
    if (uie != null)
    {
        uie.RemoveHandler(AquariumFilter.NeedsCleaningEvent, handler);
    }
}
Public Shared ReadOnly NeedsCleaningEvent As RoutedEvent = EventManager.RegisterRoutedEvent("NeedsCleaning", RoutingStrategy.Bubble, GetType(RoutedEventHandler), GetType(AquariumFilter))
Public Shared Sub AddNeedsCleaningHandler(ByVal d As DependencyObject, ByVal handler As RoutedEventHandler)
    Dim uie As UIElement = TryCast(d, UIElement)
    If uie IsNot Nothing Then
        uie.AddHandler(AquariumFilter.NeedsCleaningEvent, handler)
    End If
End Sub
Public Shared Sub RemoveNeedsCleaningHandler(ByVal d As DependencyObject, ByVal handler As RoutedEventHandler)
    Dim uie As UIElement = TryCast(d, UIElement)
    If uie IsNot Nothing Then
        uie.RemoveHandler(AquariumFilter.NeedsCleaningEvent, handler)
    End If
End Sub

Si noti che il metodo usato per stabilire il campo dell'identificatore di evento associato, RegisterRoutedEvent , è in realtà lo stesso metodo usato per registrare un evento indirizzato non collegato. Gli eventi associati e gli eventi indirizzati vengono tutti registrati in un archivio interno centralizzato. Questa implementazione dell'archivio degli eventi consente la considerazione del concetto di "eventi come interfaccia" presentata in Cenni preliminari sugli eventi indirizzati.

Generazione di un evento associato WPF

Non è in genere necessario generare eventi allegati esistenti definiti da WPF dal codice. Questi eventi seguono il modello concettuale generale "Service" e le classi di servizio, ad esempio, InputManager sono responsabili della generazione degli eventi.

Tuttavia, se si definisce un evento associato personalizzato basato sul modello WPF di base degli eventi associati in RoutedEvent , è possibile usare RaiseEvent per generare un evento associato da qualsiasi UIElement o ContentElement . Per generare un evento indirizzato (collegato o meno), è necessario dichiarare un particolare elemento nell'albero degli elementi come origine evento; tale origine viene segnalata come RaiseEvent chiamante. È responsabilità del servizio determinare quale elemento viene riportato come origine nell'albero.

Vedi anche