Panoramica degli eventi e degli eventi indirizzati

API importanti

Descriviamo il concetto di programmazione di eventi in un'app di Windows Runtime quando si usano estensioni componente C#, Visual Basic o Visual C++(C++/CX) come linguaggio di programmazione e XAML per la definizione dell'interfaccia utente. Puoi assegnare gestori per gli eventi come parte delle dichiarazioni per gli elementi dell'interfaccia utente in XAML, oppure puoi aggiungere i gestori nel codice. Windows Runtime supporta eventi indirizzati: alcuni eventi di input ed eventi di dati possono essere gestiti da oggetti oltre l'oggetto che ha generato l'evento. Gli eventi indirizzati sono utili quando si definiscono i modelli di controllo, o si usano pagine o contenitori di layout.

Eventi come concetto di programmazione

In generale, i concetti relativi agli eventi durante la programmazione di un'app di Windows Runtime sono simili al modello di evento nei linguaggi di programmazione più diffusi. Se si sa come usare già gli eventi microsoft .NET o C++, si ha un inizio iniziale. Tuttavia, non è necessario sapere molto sui concetti del modello di evento per eseguire alcune attività di base, ad esempio l'associazione di gestori.

Quando si usa C#, Visual Basic o C++/CX come linguaggio di programmazione, l'interfaccia utente viene definita nel markup (XAML). Nella sintassi di markup XAML alcuni dei principi di connessione degli eventi tra gli elementi di markup e le entità del codice di runtime sono simili ad altre tecnologie Web, ad esempio ASP.NET o HTML5.

Nota Il codice che fornisce la logica di runtime per un'interfaccia utente definita da XAML viene spesso definito come code-behind o il file code-behind. Nelle visualizzazioni della soluzione Microsoft Visual Studio questa relazione viene visualizzata graficamente, con il file code-behind dipendente e annidato rispetto alla pagina XAML a cui fa riferimento.

Button.Click: introduzione agli eventi e XAML

Una delle attività di programmazione più comuni per un'app di Windows Runtime consiste nell'acquisire l'input dell'utente nell'interfaccia utente. Ad esempio, l'interfaccia utente potrebbe avere un pulsante che l'utente deve fare clic per inviare informazioni o per modificare lo stato.

Definire l'interfaccia utente per l'app di Windows Runtime generando XAML. Questo codice XAML è in genere l'output di un'area di progettazione in Visual Studio. Si può anche scrivere il codice XAML in un editor di testo normale o in un editor XAML di terzi. Durante la generazione di questo codice XAML, si può collegare gestori eventi per singoli elementi dell'interfaccia utente contemporaneamente che definisca tutti gli altri attributi XAML che stabiliscono i valori delle proprietà di tale elemento dell'interfaccia utente.

Per collegare gli eventi in XAML, specificare il nome in formato stringa del metodo del gestore già definito o definito in un secondo momento nel code-behind. Ad esempio, questo codice XAML definisce un oggetto Button con altre proprietà (attributo x:Name, Content) assegnato come attributi e collega un gestore per l'evento Click facendo riferimento a un metodo denominato ShowUpdatesButton_Click:

<Button x:Name="showUpdatesButton"
  Content="{Binding ShowUpdatesText}"
  Click="ShowUpdatesButton_Click"/>

SuggerimentoCablaggio eventi è un termine di programmazione. Fa riferimento al processo o al codice in cui si indicano che le occorrenze di un evento devono richiamare un metodo del gestore denominato. Nella maggior parte dei modelli di codice procedurali, il cablaggio degli eventi è un codice "AddHandler" implicito o esplicito che denomina sia l'evento che il metodo e in genere implica un'istanza dell'oggetto di destinazione. In XAML, "AddHandler" è implicito e il cablaggio degli eventi è costituito interamente dalla denominazione dell'evento come nome dell'attributo di un elemento oggetto e dalla denominazione del gestore come valore dell'attributo.

Scrivere il gestore effettivo nel linguaggio di programmazione che si usa per tutto il codice e il code-behind dell'app. Con l'attributo Click="ShowUpdatesButton_Click", si è creato un contratto che quando XAML viene compilato e analizzato, sia il passaggio di compilazione del markup XAML nell'azione di compilazione dell'IDE che l'analisi XAML finale quando l'app carica può trovare un metodo denominato ShowUpdatesButton_Click come parte del codice dell'app. ShowUpdatesButton_Click deve essere un metodo che implementa una firma del metodo compatibile (basata su un delegato) per qualsiasi gestore dell'evento Click . Ad esempio, questo codice definisce il gestore ShowUpdatesButton_Click.

private void ShowUpdatesButton_Click (object sender, RoutedEventArgs e) 
{
    Button b = sender as Button;
    //more logic to do here...
}
Private Sub ShowUpdatesButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    Dim b As Button = CType(sender, Button)
    '  more logic to do here...
End Sub
void winrt::MyNamespace::implementation::BlankPage::ShowUpdatesButton_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e)
{
    auto b{ sender.as<Windows::UI::Xaml::Controls::Button>() };
    // More logic to do here.
}
void MyNamespace::BlankPage::ShowUpdatesButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) 
{
    Button^ b = (Button^) sender;
    //more logic to do here...
}

In questo esempio il ShowUpdatesButton_Click metodo si basa sul delegato RoutedEventHandler. Si sa che si tratta del delegato da usare perché si noterà che il delegato denominato nella sintassi per il metodo Click.

Suggerimento Visual Studio offre un modo pratico per denominare il gestore eventi e definire il metodo del gestore durante la modifica di XAML. Quando si specifica il nome dell'attributo dell'evento nell'editor di testo XAML, attendere qualche istante finché non viene visualizzato un elenco di Microsoft IntelliSense. Se si fa clic su <Nuovo gestore eventi> dall'elenco, Microsoft Visual Studio suggerisce un nome di metodo in base al nome x:Name dell'elemento (o al nome del tipo), al nome dell'evento e a un suffisso numerico. È quindi possibile fare clic con il pulsante destro del mouse sul nome del gestore eventi selezionato e scegliere Passa al gestore eventi. Verrà visualizzata direttamente la definizione del gestore eventi appena inserita, come illustrato nella visualizzazione dell'editor di codice del file code-behind per la pagina XAML. Il gestore eventi ha già la firma corretta, inclusi il parametro sender e la classe di dati dell'evento usata dall'evento. Inoltre, se esiste già un metodo del gestore con la firma corretta nel code-behind, il nome del metodo viene visualizzato nell'elenco a discesa completamento automatico insieme all'opzione <Nuovo gestore eventi>. È anche possibile premere tabulazioni come tasto di scelta rapida anziché fare clic sugli elementi dell'elenco IntelliSense.

Definizione di un gestore degli eventi

Per gli oggetti che sono elementi dell'interfaccia utente e dichiarati in XAML, il codice del gestore eventi viene definito nella classe parziale che funge da code-behind per una pagina XAML. I gestori eventi sono metodi scritti come parte della classe parziale associata al codice XAML. Questi gestori eventi si basano sui delegati usati da un determinato evento. I metodi del gestore eventi possono essere pubblici o privati. L'accesso privato funziona perché il gestore e l'istanza creati dal codice XAML vengono aggiunti alla generazione del codice. In generale, è consigliabile rendere privati i metodi del gestore eventi nella classe.

Nota I gestori eventi per C++ non vengono definiti nelle classi parziali, vengono dichiarati nell'intestazione come membro di classe privata. Le azioni di compilazione per un progetto C++ si occupano della generazione di codice che supporta il sistema di tipi XAML e il modello code-behind per C++.

Parametri del mittente e dati dell'evento

Il gestore scritto per l'evento può accedere a due valori disponibili come input per ogni caso in cui viene richiamato il gestore. Il primo di questi valori è sender, che è un riferimento all'oggetto in cui è associato il gestore. Il parametro sender viene digitato come tipo object di base. Una tecnica comune consiste nel eseguire il cast del mittente in un tipo più preciso. Questa tecnica è utile se si prevede di controllare o modificare lo stato sull'oggetto mittente stesso. In base alla progettazione dell'app personalizzata, in genere si conosce un tipo a cui eseguire il cast del mittente, in base alla posizione in cui il gestore è associato o ad altre specifiche di progettazione.

Il secondo valore è costituito dai dati dell'evento, che in genere vengono visualizzati nelle definizioni di sintassi come parametro e. È possibile individuare le proprietà per i dati dell'evento disponibili esaminando il parametro e del delegato assegnato per l'evento specifico gestito e quindi usando IntelliSense o Visualizzatore oggetti in Visual Studio. In alternativa, è possibile usare la documentazione di riferimento di Windows Runtime.

Per alcuni eventi, i valori di proprietà specifici dei dati dell'evento sono importanti quanto sapere che si è verificato l'evento. Ciò vale soprattutto per gli eventi di input. Per gli eventi del puntatore, la posizione del puntatore quando si è verificato l'evento potrebbe essere importante. Per gli eventi della tastiera, tutti i tasti possibili attivano un evento KeyDown e KeyUp. Per determinare il tasto premuto da un utente, è necessario accedere a KeyRoutedEventArgs disponibile per il gestore eventi. Per altre info sulla gestione degli eventi di input, vedere Interazioni tramite tastiera e Gestire l'input del puntatore. Gli eventi di input e gli scenari di input includono spesso considerazioni aggiuntive non trattate in questo argomento, ad esempio l'acquisizione del puntatore per gli eventi del puntatore e i tasti di modifica e i codici dei tasti della piattaforma per gli eventi della tastiera.

Gestori eventi che usano il modello asincrono

In alcuni casi è consigliabile usare le API che usano un modello asincrono all'interno di un gestore eventi. Ad esempio, è possibile usare un pulsante in un controllo AppBar per visualizzare una selezione file e interagire con esso. Tuttavia, molte delle API di selezione file sono asincrone. Devono essere chiamati all'interno di un ambito asincrono/awaitable e il compilatore lo applicherà. È quindi possibile aggiungere la parola chiave asincrona al gestore eventi in modo che il gestore sia ora asincrono void. Ora il gestore eventi è autorizzato a effettuare chiamate asincrone/awaitable.

Per un esempio di gestione degli eventi di interazione utente usando il modello asincrono, vedere Accesso ai file e selezione (parte della serie Creare la prima app di Windows Runtime con le serie C# o Visual Basic). Vedere anche [Chiamare API asincrone in C).

Aggiunta di gestori eventi nel codice

XAML non è l'unico modo per assegnare un gestore eventi a un oggetto . Per aggiungere gestori eventi a qualsiasi oggetto specificato nel codice, inclusi gli oggetti che non sono utilizzabili in XAML, si può usare la sintassi specifica del linguaggio per aggiungere gestori eventi.

In C# la sintassi consiste nell'usare l'operatore +=. Per registrare il gestore, fare riferimento al nome del metodo del gestore eventi sul lato destro dell'operatore.

Se si usa il codice per aggiungere gestori eventi a oggetti visualizzati nell'interfaccia utente di runtime, una procedura comune consiste nell'aggiungere tali gestori in risposta a un evento o un callback della durata di un oggetto, ad esempio Loaded o OnApplyTemplate, in modo che i gestori eventi nell'oggetto pertinente siano pronti per gli eventi avviati dall'utente in fase di esecuzione. Questo esempio mostra una struttura XAML della struttura della pagina e quindi fornisce la sintassi del linguaggio C# per l'aggiunta di un gestore eventi a un oggetto .

<Grid x:Name="LayoutRoot" Loaded="LayoutRoot_Loaded">
  <StackPanel>
    <TextBlock Name="textBlock1">Put the pointer over this text</TextBlock>
...
  </StackPanel>
</Grid>
void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
    textBlock1.PointerEntered += textBlock1_PointerEntered;
    textBlock1.PointerExited += textBlock1_PointerExited;
}

Nota Esiste una sintassi più dettagliata. Nel 2005 C# ha aggiunto una funzionalità denominata inferenza del delegato, che consente a un compilatore di dedurre la nuova istanza del delegato e di abilitare la sintassi precedente e più semplice. La sintassi dettagliata è funzionalmente identica all'esempio precedente, ma crea in modo esplicito una nuova istanza del delegato prima di registrarla, quindi non sfrutta l'inferenza del delegato. Questa sintassi esplicita è meno comune, ma potrebbe essere ancora visualizzata in alcuni esempi di codice.

void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
    textBlock1.PointerEntered += new PointerEventHandler(textBlock1_PointerEntered);
    textBlock1.PointerExited += new MouseEventHandler(textBlock1_PointerExited);
}

Esistono due possibilità per la sintassi di Visual Basic. Uno consiste nel parallelare la sintassi C# e collegare i gestori direttamente alle istanze. Ciò richiede la parola chiave AddHandler e anche l'operatore AddressOf che dereferenzia il nome del metodo del gestore.

L'altra opzione per la sintassi di Visual Basic consiste nell'usare la parola chiave Handle nei gestori eventi. Questa tecnica è appropriata per i casi in cui si prevede che i gestori esistano negli oggetti in fase di caricamento e persistono per tutta la durata dell'oggetto. L'uso di Handles in un oggetto definito in XAML richiede che venga specificato un Nome / x:Name. Questo nome diventa il qualificatore di istanza necessario per la parte Instance.Event della sintassi Handle. In questo caso non è necessario un gestore eventi basato sulla durata degli oggetti per avviare il collegamento degli altri gestori eventi; le connessioni Handle vengono create durante la compilazione della pagina XAML.

Private Sub textBlock1_PointerEntered(ByVal sender As Object, ByVal e As PointerRoutedEventArgs) Handles textBlock1.PointerEntered
' ...
End Sub

Nota Visual Studio e la relativa area di progettazione XAML promuovono in genere la tecnica di gestione delle istanze anziché la parola chiave Handle. Ciò è dovuto al fatto che la definizione del cablaggio del gestore eventi in XAML fa parte del tipico flusso di lavoro dello sviluppatore della finestra di progettazione e la tecnica delle parole chiave Handle non è compatibile con il collegamento dei gestori eventi in XAML.

In C++/CX si usa anche la sintassi += , ma esistono differenze rispetto al formato C# di base:

  • Non esiste alcuna inferenza del delegato, pertanto è necessario usare ref new per l'istanza del delegato.
  • Il costruttore delegato ha due parametri e richiede l'oggetto di destinazione come primo parametro. In genere si specifica questo.
  • Il costruttore delegato richiede l'indirizzo del metodo come secondo parametro, quindi l'operatore di riferimento & precede il nome del metodo.
textBlock1().PointerEntered({this, &MainPage::TextBlock1_PointerEntered });
textBlock1->PointerEntered += 
ref new PointerEventHandler(this, &BlankPage::textBlock1_PointerEntered);

Rimozione dei gestori eventi nel codice

In genere non è necessario rimuovere i gestori eventi nel codice, anche se sono stati aggiunti nel codice. Il comportamento della durata degli oggetti per la maggior parte degli oggetti di Windows Runtime, ad esempio pagine e controlli, eliminerà definitivamente gli oggetti quando vengono disconnessi dalla finestra principale e dalla relativa struttura ad albero visuale e anche tutti i riferimenti delegati vengono eliminati definitivamente. .NET esegue questa operazione tramite Garbage Collection e Windows Runtime con C++/CX usa riferimenti deboli per impostazione predefinita.

Esistono alcuni rari casi in cui si vogliono rimuovere in modo esplicito i gestori eventi. tra cui:

  • Gestori aggiunti per gli eventi statici, che non possono ottenere il Garbage Collection in modo convenzionale. Esempi di eventi statici nell'API di Windows Runtime sono gli eventi delle classi CompositionTarget e Clipboard.
  • Testare il codice in cui si vuole che la rimozione del gestore sia immediata o il codice in cui si desidera scambiare i gestori eventi precedenti/nuovi per un evento in fase di esecuzione.
  • Implementazione di una funzione di accesso di rimozione personalizzata.
  • Eventi statici personalizzati.
  • Gestori per gli spostamenti di pagina.

FrameworkElement.Unloaded o Page.NavigatedFrom sono possibili trigger di evento con posizioni appropriate nella gestione dello stato e nella durata degli oggetti, in modo che sia possibile usarli per rimuovere i gestori per altri eventi.

Ad esempio, è possibile rimuovere un gestore eventi denominato textBlock1_PointerEntered dall'oggetto di destinazione textBlock1 usando questo codice.

textBlock1.PointerEntered -= textBlock1_PointerEntered;
RemoveHandler textBlock1.PointerEntered, AddressOf textBlock1_PointerEntered

È possibile anche rimuovere i gestori per i casi in cui l'evento è stato aggiunto tramite un attributo XAML, il che significa che il gestore è stato aggiunto nel codice generato. Questa operazione è più semplice se è stato specificato un valore Name per l'elemento in cui è stato associato il gestore, perché fornisce un riferimento all'oggetto per il codice in un secondo momento. Tuttavia, è anche possibile camminare sull'albero degli oggetti per trovare il riferimento all'oggetto necessario nei casi in cui l'oggetto non ha nome.

Se è necessario rimuovere un gestore eventi in C++/CX, è necessario un token di registrazione, che dovrebbe essere stato ricevuto dal valore restituito della registrazione del += gestore eventi. Questo perché il valore usato per il lato destro della -= deregistrazione nella sintassi C++/CX è il token, non il nome del metodo. Per C++/CX, non è possibile rimuovere i gestori aggiunti come attributo XAML perché il codice generato da C++/CX non salva un token.

Eventi indirizzati

Windows Runtime con C#, Microsoft Visual Basic o C++/CX supporta il concetto di evento indirizzato per un set di eventi presenti nella maggior parte degli elementi dell'interfaccia utente. Questi eventi sono destinati agli scenari di input e interazione dell'utente e vengono implementati nella classe di base UIElement. Ecco un elenco di eventi di input indirizzati:

Un evento indirizzato è un evento potenzialmente passato (indirizzato) da un oggetto figlio a ognuno dei relativi oggetti padre successivi in un albero di oggetti. La struttura XAML dell'interfaccia utente approssima questo albero, con la radice di tale albero come elemento radice in XAML. L'albero degli oggetti true può variare in qualche modo rispetto all'annidamento degli elementi XAML, perché l'albero degli oggetti non include funzionalità del linguaggio XAML, ad esempio i tag degli elementi proprietà. È possibile concepire l'evento indirizzato come bubbling da qualsiasi elemento figlio dell'elemento oggetto XAML che genera l'evento, verso l'elemento oggetto padre che lo contiene. L'evento e i relativi dati dell'evento possono essere gestiti su più oggetti lungo la route dell'evento. Se nessun elemento dispone di gestori, la route continua potenzialmente fino a raggiungere l'elemento radice.

Se si conoscono tecnologie Web come DHTML (Dynamic HTML) o HTML5, si potrebbe avere già familiarità con il concetto di evento di bubbling.

Quando un evento indirizzato passa attraverso la route evento, tutti i gestori eventi associati accedono a un'istanza condivisa dei dati dell'evento. Pertanto, se uno dei dati dell'evento è scrivibile da un gestore, eventuali modifiche apportate ai dati dell'evento verranno passate al gestore successivo e potrebbero non rappresentare più i dati originali dell'evento dall'evento. Quando un evento ha un comportamento di evento indirizzato, la documentazione di riferimento includerà osservazioni o altre notazioni sul comportamento indirizzato.

Proprietà OriginalSource di RoutedEventArgs

Quando un evento aumenta una route di eventi, il mittente non è più lo stesso oggetto dell'oggetto che genera eventi. Il mittente è invece l'oggetto in cui è associato il gestore richiamato.

In alcuni casi, il mittente non è interessante e si è invece interessati a informazioni come quale dei possibili oggetti figlio il puntatore si trova quando viene generato un evento di puntatore o quale oggetto in un'interfaccia utente più grande ha mantenuto lo stato attivo quando un utente ha premuto un tasto di tastiera. Per questi casi, è possibile usare il valore della proprietà OriginalSource. In tutti i punti della route, OriginalSource viene segnalato l'oggetto originale che ha generato l'evento, anziché l'oggetto in cui è associato il gestore. Tuttavia, per gli eventi di input UIElement, l'oggetto originale è spesso un oggetto che non è immediatamente visibile nel codice XAML della definizione dell'interfaccia utente a livello di pagina. L'oggetto di origine originale potrebbe invece essere una parte di un controllo basato su modelli. Ad esempio, se l'utente passa il puntatore sul bordo di un Pulsante, per la maggior parte degli eventi il puntatore OriginalSource è una parte del modello Border nel Modello, non il Pulsante stesso.

Suggerimento l'evento di input bubbling è particolarmente utile se si sta creando un controllo basato su modelli. Qualsiasi controllo con un modello può avere un nuovo modello applicato dal consumer. Il consumer che sta tentando di ricreare un modello di lavoro potrebbe eliminare involontariamente alcune operazioni di gestione degli eventi dichiarate nel modello predefinito. È comunque possibile fornire la gestione degli eventi a livello di controllo collegando i gestori come parte dell'override OnApplyTemplate nella definizione della classe. È quindi possibile rilevare gli eventi di input che si inserisce nella radice del controllo alla creazione di istanze.

Proprietà Handled

Diverse classi di dati di evento per eventi indirizzati specifici contengono una proprietà denominata Handled. Per esempi, vedere PointerRoutedEventArgs.Handled, KeyRoutedEventArgs.Handled, DragEventArgs.Handled. In tutti i casi Handled è una proprietà booleana impostabile.

L'impostazione della proprietà Handled su true influisce sul comportamento del sistema eventi. Quando Handled è true, il routing si arresta per la maggior parte dei gestori eventi. L'evento non continua lungo la route per notificare ad altri gestori collegati di quel particolare caso evento. Cosa significa "gestito" nel contesto dell'evento e il modo in cui l'app risponde all'utente. In pratica, Handled è un protocollo semplice che consente al codice dell'app di dichiarare che un evento non deve passare a un contenitore, la logica dell'app ha preso in considerazione le operazioni eseguite. Al contrario, è necessario prestare attenzione a non gestire eventi che probabilmente dovrebbero generare bolle in modo che i comportamenti del sistema o del controllo predefiniti possano agire. Ad esempio, la gestione di eventi di basso livello all'interno delle parti o degli elementi di un controllo di selezione può essere dannosa. Il controllo di selezione potrebbe cercare eventi di input per sapere che la selezione deve cambiare.

Non tutti gli eventi indirizzati possono annullare una route in questo modo ed è possibile indicare che perché non avranno una proprietà Handled. Ad esempio, GotFocus e LostFocus fanno bolle, ma si spostano sempre fino alla radice e le classi di dati dell'evento non hanno una proprietà Handled che può influenzare tale comportamento.

Gestori eventi di input nei controlli

Controlli specifici di Windows Runtime usano talvolta il concetto Handled per gli eventi di input internamente. Questo può far sembrare che non si verifichi mai un evento di input, perché il codice utente non può gestirlo. Ad esempio, la classe Button include la logica che gestisce deliberatamente l'evento di input generale PointerPressed. Lo fa perché i pulsanti generano un evento Click avviato dall'input premuto dal puntatore, nonché da altre modalità di input, ad esempio la gestione dei tasti come il tasto Invio che può richiamare il pulsante quando è attivo. Ai fini della progettazione della classe Button, l'evento di input non elaborato viene gestito concettualmente e i consumer di classi, ad esempio il codice utente, possono interagire con l'evento Click pertinente al controllo. Gli argomenti per classi di controllo specifiche nel riferimento all'API di Windows Runtime spesso notano il comportamento di gestione degli eventi implementato dalla classe . In alcuni casi, è possibile modificare il comportamento eseguendo l'override dei metodi OnEvent. Ad esempio, è possibile modificare il modo in cui la classe derivata TextBox reagisce all'input della chiave eseguendo l'override di Control.OnKeyDown.

Registrazione dei gestori per gli eventi indirizzati già gestiti

In precedenza si è detto che l'impostazione di Handled su true impedisce la chiamata della maggior parte dei gestori. Ma il metodo AddHandler fornisce una tecnica in cui è possibile associare un gestore che viene sempre richiamato per la route, anche se un altro gestore precedente nella route ha impostato Handled su true nei dati dell'evento condiviso. Questa tecnica è utile se un controllo in uso ha gestito l'evento nella composizione interna o per la logica specifica del controllo. ma si vuole comunque rispondere da un'istanza del controllo o dall'interfaccia utente dell'app. Ma usare questa tecnica con cautela, perché può contraddire lo scopo di Handled e possibilmente interrompere le interazioni desiderate di un controllo.

Solo gli eventi indirizzati con un identificatore di evento indirizzato corrispondente possono usare la tecnica di gestione degli eventi AddHandler , perché l'identificatore è un input obbligatorio del metodo AddHandler. Vedere la documentazione di riferimento per AddHandler per un elenco di eventi con identificatori di evento indirizzati disponibili. Nella maggior parte dei casi questo è lo stesso elenco di eventi indirizzati mostrati in precedenza. L'eccezione è che gli ultimi due nell'elenco: GotFocus e LostFocus non hanno un identificatore di evento indirizzato, quindi non è possibile usare AddHandler per tali elementi.

Eventi indirizzati all'esterno della struttura ad albero visuale

Alcuni oggetti partecipano a una relazione con la struttura ad albero visuale principale concettualmente simile alla presenza di una sovrimpressione sugli oggetti visivi principali. Questi oggetti non fanno parte delle normali relazioni padre-figlio che connettono tutti gli elementi della struttura ad albero alla radice visiva. Questo è il caso di qualsiasi Popup o ToolTip visualizzato. Se si desidera gestire gli eventi indirizzati da un Popup o ToolTip, posizionare i gestori su elementi dell'interfaccia utente specifici che si trovano all'interno del Popup o ToolTip e non gli elementi Popup o ToolTip stessi. Non fare affidamento sul routing all'interno di qualsiasi composizione eseguita per il contenuto Popup o ToolTip. Ciò è dovuto al fatto che il routing degli eventi per gli eventi indirizzati funziona solo lungo la struttura ad albero visuale principale. Un Popup o ToolTip non è considerato un elemento padre degli elementi dell'interfaccia utente sussidiaria e non riceve mai l'evento indirizzato, anche se sta tentando di usare uno sfondo predefinito Popup come area di acquisizione per gli eventi di input.

Hhit test ed eventi di input

Determinare se e dove nell'interfaccia utente un elemento è visibile al mouse, al tocco e all'input dello stilo viene chiamato hit testing. Per le azioni di tocco e anche per gli eventi di manipolazione o specifici dell'interazione che sono conseguenze di un'azione di tocco, un elemento deve essere visibile per essere l'origine evento e generare l'evento associato all'azione. In caso contrario, l'azione passa attraverso l'elemento a tutti gli elementi sottostanti o elementi padre nella struttura ad albero visuale che potrebbero interagire con tale input. Esistono diversi fattori che influiscono sull'hit testing, ma è possibile determinare se un determinato elemento può generare eventi di input controllando la relativa proprietà IsHitTestVisible. Questa proprietà restituisce true solo se l'elemento soddisfa questi criteri:

  • Il valore della proprietà Visibility dell'elemento è Visible.
  • Il valore della proprietà Background o Fill dell'elemento non è null. Un valore Pennello null restituisce trasparenza e invisibilità hit test. (Per rendere trasparente un elemento ma anche hit testable, usare un Pennello trasparente invece di null).

NotaBackground e Fill non sono definiti da UIElement e sono invece definiti da classi derivate diverse, ad esempio Control e Shape. Ma le implicazioni dei pennelli usati per le proprietà in primo piano e in background sono le stesse per gli eventi di hit testing e di input, indipendentemente dalla sottoclasse che implementa le proprietà.

  • Se l'elemento è un controllo, il valore della proprietà IsEnabled deve essere true.
  • L'elemento deve avere dimensioni effettive nel layout. Un elemento in cui ActualHeight e ActualWidth sono 0 non genera eventi di input.

Alcuni controlli hanno regole speciali per l'hit testing. Ad esempio, TextBlock non ha proprietà Background, ma è ancora hit testable all'interno dell'intera area delle relative dimensioni. I controlli Image e MediaElement sono sottoposti a hit test sulle dimensioni del rettangolo definite, indipendentemente dal contenuto trasparente, ad esempio il canale alfa nel file di origine multimediale visualizzato. I controlli WebView hanno un comportamento speciale di hit testing perché l'input può essere gestito dagli eventi HTML ospitati e genera script.

La maggior parte delle classi Panel e Border non sono hit testable in background, ma possono comunque gestire gli eventi di input utente indirizzati dagli elementi che contengono.

È possibile determinare quali elementi si trovano nella stessa posizione di un evento di input dell'utente, indipendentemente dal fatto che gli elementi siano hit testable. A tale scopo, chiamare il metodo FindElementsInHostCoordinates. Come suggerisce il nome, questo metodo trova gli elementi in una posizione relativa a un elemento host specificato. Tuttavia, le trasformazioni applicate e le modifiche di layout possono regolare il sistema di coordinate relative di un elemento e quindi influire sugli elementi trovati in una determinata posizione.

Esecuzione di comandi

Un numero ridotto di elementi dell'interfaccia utente supporta il comando. L'esecuzione dei comandi usa eventi indirizzati correlati all'input nell'implementazione sottostante e consente l'elaborazione dell'input dell'interfaccia utente correlato (un'azione del puntatore, un tasto di scelta rapida specifico) richiamando un singolo gestore comandi. Se il comando è disponibile per un elemento dell'interfaccia utente, è consigliabile usare le API di comando anziché gli eventi di input discreti. In genere si usa un riferimento Binding nelle proprietà di una classe che definisce il modello di visualizzazione per i dati. Le proprietà contengono comandi denominati che implementano il modello di comando ICommand specifico del linguaggio. Per altre info, vedi ButtonBase.Command.

Eventi personalizzati in Windows Runtime

Ai fini della definizione di eventi personalizzati, il modo in cui si aggiunge l'evento e ciò che significa per la progettazione della classe dipende in modo elevato dal linguaggio di programmazione in uso.

  • Per C# e Visual Basic si definisce un evento CLR. È possibile usare il modello di evento .NET standard, purché non si usino funzioni di accesso personalizzate (aggiunta/rimozione). Suggerimenti aggiuntivi:
  • Per C++/CX, vedere Eventi (C++/CX).
    • Usare riferimenti denominati anche per i propri utilizzi di eventi personalizzati. Non usare lambda per eventi personalizzati, potrebbe creare un riferimento circolare.

Non è possibile dichiarare un evento indirizzato personalizzato per Windows Runtime; gli eventi indirizzati sono limitati al set proveniente da Windows Runtime.

La definizione di un evento personalizzato viene in genere eseguita come parte dell'esercizio di definizione di un controllo personalizzato. Si tratta di un modello comune per avere una proprietà di dipendenza con un callback modificato dalla proprietà e per definire anche un evento personalizzato generato dal callback della proprietà di dipendenza in alcuni o tutti i casi. I consumer del controllo non hanno accesso al callback modificato dalla proprietà definita, ma la disponibilità di un evento di notifica è la cosa migliore. Per altre informazioni, vedere Proprietà di dipendenza personalizzate.