Cenni preliminari sull'input

Il Windows Presentation Foundation (WPF) sottosistema fornisce un'API potente per ottenere input da un'ampia gamma di dispositivi, tra cui mouse, tastiera, tocco e stilo. Questo argomento descrive i servizi forniti da WPF e illustra l'architettura dei sistemi di input.

API di input

L'esposizione dell'API di input primaria si trova nelle classi degli elementi di base: UIElement , ContentElement , FrameworkElement e FrameworkContentElement . Per altre informazioni sugli elementi di base, vedere Cenni preliminari sugli elementi di base. Queste classi forniscono funzionalità per gli eventi di input correlati, ad esempio, a pressioni di tasti, pulsanti del mouse, rotellina del mouse, movimento del mouse, gestione dello stato attivo, stato mouse capture e altro. Inserendo l'API di input sugli elementi di base, anziché considerare tutti gli eventi di input come servizio, l'architettura di input consente agli eventi di input di essere originati da un determinato oggetto nell'interfaccia utente e di supportare uno schema di routing degli eventi in base al quale più di un elemento ha la possibilità di gestire un evento di input. A molti eventi di input è associata una coppia di eventi. Ad esempio, l'evento di riduzione della chiave è associato KeyDown agli PreviewKeyDown eventi e. La differenza tra questi eventi consiste nel modo in cui ne viene eseguito il routing all'elemento di destinazione. Gli eventi di anteprima scendono lungo l'albero degli elementi (tunneling), dall'elemento radice all'elemento di destinazione. Gli eventi di bubbling invece salgono dall'elemento di destinazione all'elemento radice. Il routing degli eventi in WPF è illustrato in modo più dettagliato più avanti in questo articolo e nell'articolo Cenni preliminari sugli eventi indirizzati.

Classi Keyboard e Mouse

Oltre all'API di input sulle classi degli elementi di base, la Keyboard classe e le Mouse classi forniscono un'API aggiuntiva per lavorare con l'input della tastiera e del mouse.

Esempi di API di input nella Keyboard classe sono la Modifiers proprietà, che restituisce l'oggetto ModifierKeys attualmente premuto, e il IsKeyDown metodo, che determina se viene premuto un tasto specificato.

Nell'esempio seguente viene usato il GetKeyStates metodo per determinare se un oggetto Key è in stato di inattività.

// Uses the Keyboard.GetKeyStates to determine if a key is down.
// A bitwise AND operation is used in the comparison.
// e is an instance of KeyEventArgs.
if ((Keyboard.GetKeyStates(Key.Return) & KeyStates.Down) > 0)
{
    btnNone.Background = Brushes.Red;
}
' Uses the Keyboard.GetKeyStates to determine if a key is down.
' A bitwise AND operation is used in the comparison. 
' e is an instance of KeyEventArgs.
If (Keyboard.GetKeyStates(Key.Return) And KeyStates.Down) > 0 Then
    btnNone.Background = Brushes.Red

Esempi di API di input nella Mouse classe sono MiddleButton , che ottiene lo stato del pulsante centrale del mouse e DirectlyOver , che ottiene l'elemento sul quale è attualmente posizionato il puntatore del mouse.

Nell'esempio seguente viene determinato se l'oggetto LeftButton sul mouse è nello Pressed stato.

if (Mouse.LeftButton == MouseButtonState.Pressed)
{
    UpdateSampleResults("Left Button Pressed");
}
If Mouse.LeftButton = MouseButtonState.Pressed Then
    UpdateSampleResults("Left Button Pressed")
End If

Le Mouse Keyboard classi e sono descritte in modo più dettagliato in questa panoramica.

Input dello stilo

WPF dispone del supporto integrato per il Stylus . StylusÈ un input penna reso popolare dal Tablet PC. WPF le applicazioni possono trattare lo stilo come mouse usando l'API del mouse, ma WPF anche un'astrazione del dispositivo stilo che usa un modello simile a quello della tastiera e del mouse. Tutte le API correlate allo stilo contengono la parola "stilo".

Dal momento che lo stilo può funzionare come un mouse, le applicazioni che supportano solo l'input del mouse possono comunque ottenere automaticamente un certo livello di supporto dello stilo. Quando lo stilo viene usato in questo modo, l'applicazione può gestire l'evento dello stilo appropriato gestendo l'evento del mouse corrispondente. Inoltre, tramite l'astrazione del dispositivo stilo, sono disponibili anche servizi di livello superiore, come l'input penna. Per altre informazioni sull'input penna, vedere Nozioni di base sull'input penna.

Routing di eventi

Un oggetto FrameworkElement può contenere altri elementi come elementi figlio nel relativo modello di contenuto, formando una struttura ad albero di elementi. In WPF l'elemento padre può partecipare all'input diretto verso i relativi elementi figlio o agli altri discendenti mediante la gestione degli eventi. Ciò risulta particolarmente utile per la creazione di controlli a partire da controlli più piccoli, processo noto come "composizione di controlli" o "composizione". Per altre informazioni sugli alberi degli elementi e sulla loro relazione con le route degli eventi, vedere Strutture ad albero in WPF.

Il routing degli eventi è il processo di inoltro degli eventi a più elementi, in modo che un oggetto o un elemento specifico lungo la route possa offrire una risposta significativa (tramite la gestione) a un evento che potrebbe essere stato originato da un elemento diverso. Gli eventi indirizzati usano uno dei tre meccanismi di routing indicati di seguito: diretto, bubbling e tunneling. Nel routing diretto, l'elemento di origine è l'unico elemento che riceve la notifica e l'evento non viene indirizzato a nessun altro elemento. Tuttavia, l'evento indirizzato diretto offre ancora alcune funzionalità aggiuntive che sono presenti solo per gli eventi indirizzati anziché per gli eventi CLR standard. Il bubbling viene eseguito procedendo verso l'alto nell'albero degli elementi, notificando innanzitutto l'elemento che ha originato l'evento, quindi l'elemento padre e così via. Il tunneling parte dalla radice dell'albero degli elementi e procede verso il basso, terminando con l'elemento di origine. Per altre informazioni sugli eventi indirizzati, vedere Cenni preliminari sugli eventi indirizzati.

Gli eventi di input WPF sono in genere a coppie, costituite da un evento di tunneling e un evento di bubbling. Gli eventi di tunneling si distinguono da quelli di bubbling tramite il prefisso "Preview". Ad esempio, PreviewMouseMove è la versione di tunneling di un evento di spostamento del mouse ed MouseMove è la versione di bubbling di questo evento. Questa coppia di eventi è una convenzione implementata a livello di elemento e non è una funzionalità intrinseca del sistema di eventi WPF. Per informazioni dettagliate, vedere la sezione Eventi di input WPF in Cenni preliminari sugli eventi indirizzati.

Gestione degli eventi di input

Per ricevere input su un elemento, un gestore eventi deve essere associato a quel particolare evento. In XAML tale associazione è semplice: è sufficiente fare riferimento al nome dell'evento come attributo dell'elemento che rimarrà in ascolto di questo evento. Si imposta quindi il valore dell'attributo sul nome del gestore eventi definito, in base a un delegato. Il gestore eventi deve essere scritto nel codice, ad esempio C#, e può essere incluso in un file code-behind.

Gli eventi della tastiera si verificano quando il sistema operativo segnala azioni dei tasti eseguite quando lo stato attivo della tastiera è su un elemento. Gli eventi del mouse e dello stilo rientrano ciascuno in due categorie: eventi che segnalano modifiche nella posizione del puntatore rispetto all'elemento ed eventi che segnalano modifiche nello stato dei pulsanti del dispositivo.

Esempio di evento di input da tastiera

L'esempio seguente illustra una situazione di ascolto della pressione del tasto freccia SINISTRA. StackPanelViene creato un oggetto che dispone di un oggetto Button . Un gestore eventi per restare in attesa della pressione del tasto freccia sinistra viene collegato all' Button istanza.

Nella prima sezione dell'esempio vengono creati l'oggetto StackPanel e l'oggetto Button e viene collegato il gestore eventi per l'oggetto KeyDown .

<StackPanel>
  <Button Background="AliceBlue"
          KeyDown="OnButtonKeyDown"
          Content="Button1"/>
</StackPanel>
// Create the UI elements.
StackPanel keyboardStackPanel = new StackPanel();
Button keyboardButton1 = new Button();

// Set properties on Buttons.
keyboardButton1.Background = Brushes.AliceBlue;
keyboardButton1.Content = "Button 1";

// Attach Buttons to StackPanel.
keyboardStackPanel.Children.Add(keyboardButton1);

// Attach event handler.
keyboardButton1.KeyDown += new KeyEventHandler(OnButtonKeyDown);
' Create the UI elements.
Dim keyboardStackPanel As New StackPanel()
Dim keyboardButton1 As New Button()

' Set properties on Buttons.
keyboardButton1.Background = Brushes.AliceBlue
keyboardButton1.Content = "Button 1"

' Attach Buttons to StackPanel.
keyboardStackPanel.Children.Add(keyboardButton1)

' Attach event handler.
AddHandler keyboardButton1.KeyDown, AddressOf OnButtonKeyDown

La seconda sezione è scritta nel codice e definisce il gestore eventi. Quando viene premuto il tasto freccia sinistra con lo Button stato attivo della tastiera, il gestore viene eseguito e il Background colore di Button viene modificato. Se il tasto è premuto, ma non è il tasto freccia sinistra, il Background colore di Button viene modificato di nuovo sul colore iniziale.

private void OnButtonKeyDown(object sender, KeyEventArgs e)
{
    Button source = e.Source as Button;
    if (source != null)
    {
        if (e.Key == Key.Left)
        {
            source.Background = Brushes.LemonChiffon;
        }
        else
        {
            source.Background = Brushes.AliceBlue;
        }
    }
}
Private Sub OnButtonKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
    Dim source As Button = TryCast(e.Source, Button)
    If source IsNot Nothing Then
        If e.Key = Key.Left Then
            source.Background = Brushes.LemonChiffon
        Else
            source.Background = Brushes.AliceBlue
        End If
    End If
End Sub

Esempio di evento di input del mouse

Nell'esempio seguente, il Background colore di un oggetto Button viene modificato quando il puntatore del mouse entra in Button . Il Background colore viene ripristinato quando il mouse esce dall'oggetto Button .

La prima sezione dell'esempio crea e il StackPanel Button controllo e connette i gestori eventi per gli MouseEnter MouseLeave eventi e a Button .

<StackPanel>
  <Button Background="AliceBlue"
          MouseEnter="OnMouseExampleMouseEnter"
          MouseLeave="OnMosueExampleMouseLeave">Button
          
  </Button>
</StackPanel>
// Create the UI elements.
StackPanel mouseMoveStackPanel = new StackPanel();
Button mouseMoveButton = new Button();

// Set properties on Button.
mouseMoveButton.Background = Brushes.AliceBlue;
mouseMoveButton.Content = "Button";

// Attach Buttons to StackPanel.
mouseMoveStackPanel.Children.Add(mouseMoveButton);

// Attach event handler.
mouseMoveButton.MouseEnter += new MouseEventHandler(OnMouseExampleMouseEnter);
mouseMoveButton.MouseLeave += new MouseEventHandler(OnMosueExampleMouseLeave);
' Create the UI elements.
Dim mouseMoveStackPanel As New StackPanel()
Dim mouseMoveButton As New Button()

' Set properties on Button.
mouseMoveButton.Background = Brushes.AliceBlue
mouseMoveButton.Content = "Button"

' Attach Buttons to StackPanel.
mouseMoveStackPanel.Children.Add(mouseMoveButton)

' Attach event handler.
AddHandler mouseMoveButton.MouseEnter, AddressOf OnMouseExampleMouseEnter
AddHandler mouseMoveButton.MouseLeave, AddressOf OnMosueExampleMouseLeave

La seconda sezione dell'esempio è scritta nel codice e definisce i gestori eventi. Quando il mouse entra Button in, il Background colore di Button viene modificato in SlateGray . Quando il mouse esce Button da, il Background colore di Button viene modificato di nuovo in AliceBlue .

private void OnMouseExampleMouseEnter(object sender, MouseEventArgs e)
{
    // Cast the source of the event to a Button.
    Button source = e.Source as Button;

    // If source is a Button.
    if (source != null)
    {
        source.Background = Brushes.SlateGray;
    }
}
Private Sub OnMouseExampleMouseEnter(ByVal sender As Object, ByVal e As MouseEventArgs)
    ' Cast the source of the event to a Button.
    Dim source As Button = TryCast(e.Source, Button)

    ' If source is a Button.
    If source IsNot Nothing Then
        source.Background = Brushes.SlateGray
    End If
End Sub
private void OnMosueExampleMouseLeave(object sender, MouseEventArgs e)
{
    // Cast the source of the event to a Button.
    Button source = e.Source as Button;

    // If source is a Button.
    if (source != null)
    {
        source.Background = Brushes.AliceBlue;
    }
}
Private Sub OnMosueExampleMouseLeave(ByVal sender As Object, ByVal e As MouseEventArgs)
    ' Cast the source of the event to a Button.
    Dim source As Button = TryCast(e.Source, Button)

    ' If source is a Button.
    If source IsNot Nothing Then
        source.Background = Brushes.AliceBlue
    End If
End Sub

Input di testo

L' TextInput evento consente di ascoltare l'input di testo in modo indipendente dal dispositivo. La tastiera è il mezzo principale per l'immissione di testo, ma anche i comandi vocali, il riconoscimento della grafia e altri dispositivi di input possono generare input di testo.

Per l'input da tastiera, WPF Invia innanzitutto gli KeyDown / KeyUp eventi appropriati. Se tali eventi non vengono gestiti e la chiave è testuale, anziché una chiave di controllo come frecce direzionali o tasti funzione, TextInput viene generato un evento. Tra gli eventi e non è sempre presente un semplice mapping uno-a-uno, KeyDown / KeyUp TextInput perché più sequenze di tasti possono generare un singolo carattere di input di testo e singole sequenze di tasti possono generare stringhe multicarattere. Ciò vale soprattutto per le lingue quali il cinese, il giapponese e il coreano che usano IME (Input Method Editor) per generare le migliaia di caratteri possibili negli alfabeti corrispondenti.

Quando WPF Invia un KeyUp / KeyDown evento, Key viene impostato su Key.System se le sequenze di tasti potrebbero far parte di un TextInput evento (ad esempio, se si preme ALT + S). Ciò consente al codice in un KeyDown gestore eventi di verificare Key.System la presenza di e, se presente, di lasciare l'elaborazione per il gestore dell'evento generato successivamente TextInput . In questi casi, le varie proprietà dell' TextCompositionEventArgs argomento possono essere usate per determinare le sequenze di tasti originali. Analogamente, se un IME è attivo, Key ha il valore di Key.ImeProcessed e ImeProcessedKey assegna la sequenza di tasti originale o le sequenze di tasti.

Nell'esempio seguente viene definito un gestore per l' Click evento e un gestore per l' KeyDown evento.

Il primo segmento di codice o markup crea l'interfaccia utente.

<StackPanel KeyDown="OnTextInputKeyDown">
  <Button Click="OnTextInputButtonClick"
          Content="Open" />
  <TextBox> . . . </TextBox>
</StackPanel>
// Create the UI elements.
StackPanel textInputStackPanel = new StackPanel();
Button textInputeButton = new Button();
TextBox textInputTextBox = new TextBox();
textInputeButton.Content = "Open";

// Attach elements to StackPanel.
textInputStackPanel.Children.Add(textInputeButton);
textInputStackPanel.Children.Add(textInputTextBox);

// Attach event handlers.
textInputStackPanel.KeyDown += new KeyEventHandler(OnTextInputKeyDown);
textInputeButton.Click += new RoutedEventHandler(OnTextInputButtonClick);
' Create the UI elements.
Dim textInputStackPanel As New StackPanel()
Dim textInputeButton As New Button()
Dim textInputTextBox As New TextBox()
textInputeButton.Content = "Open"

' Attach elements to StackPanel.
textInputStackPanel.Children.Add(textInputeButton)
textInputStackPanel.Children.Add(textInputTextBox)

' Attach event handlers.
AddHandler textInputStackPanel.KeyDown, AddressOf OnTextInputKeyDown
AddHandler textInputeButton.Click, AddressOf OnTextInputButtonClick

Il secondo segmento di codice contiene i gestori eventi.

private void OnTextInputKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.O && Keyboard.Modifiers == ModifierKeys.Control)
    {
        handle();
        e.Handled = true;
    }
}

private void OnTextInputButtonClick(object sender, RoutedEventArgs e)
{
    handle();
    e.Handled = true;
}

public void handle()
{
    MessageBox.Show("Pretend this opens a file");
}
Private Sub OnTextInputKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
    If e.Key = Key.O AndAlso Keyboard.Modifiers = ModifierKeys.Control Then
        handle()
        e.Handled = True
    End If
End Sub

Private Sub OnTextInputButtonClick(ByVal sender As Object, ByVal e As RoutedEventArgs)
    handle()
    e.Handled = True
End Sub

Public Sub handle()
    MessageBox.Show("Pretend this opens a file")
End Sub

Poiché gli eventi di input compongono la route dell'evento, StackPanel riceve l'input indipendentemente dall'elemento con lo stato attivo della tastiera. Il TextBox controllo viene notificato per primo e il OnTextInputKeyDown gestore viene chiamato solo se l'oggetto TextBox non ha gestito l'input. Se PreviewKeyDown viene utilizzato l'evento anziché l' KeyDown evento, il OnTextInputKeyDown gestore viene chiamato per primo.

In questo esempio la logica di gestione viene scritta due volte, una per CTRL+O e una per l'evento Click del pulsante. È possibile semplificare questa operazione usando i comandi, invece di gestire direttamente gli eventi di input. I comandi vengono illustrati in questo articolo e in Cenni preliminari sull'esecuzione di comandi.

Tocco e manipolazione

Il nuovo hardware e le nuove API del sistema operativo Windows 7 consentono alle applicazioni di ricevere contemporaneamente input da più tocchi. WPF consente alle applicazioni di rilevare il tocco e rispondere in un modo simile alle risposte ad altri tipi di input, ad esempio di mouse o tastiera, generando eventi quando si verifica il tocco.

WPF espone due tipi di eventi quando si verifica il tocco: eventi di tocco ed eventi di manipolazione. Gli eventi di tocco forniscono dati non elaborati relativi a ogni dito appoggiato su un touchscreen e al suo movimento. Gli eventi di manipolazione interpretano l'input come azioni specifiche. Questa sezione illustra entrambi i tipi di eventi.

Prerequisiti

Per sviluppare un'applicazione che risponde al tocco, sono necessari i componenti seguenti.

  • Visual Studio 2010.

  • Windows 7.

  • Un dispositivo, ad esempio un touchscreen, che supporta Windows Touch.

Terminologia

Quando si parla di tocco, vengono usati i termini seguenti.

  • Tocco è un tipo di input dell'utente riconosciuto da Windows 7. In genere, il tocco viene generato appoggiando le dita su uno schermo sensibile al tocco. Si noti che dispositivi come i touchpad, diffusi sui computer portatili, non supportano il tocco se il dispositivo si limita a convertire la posizione e il movimento del dito come input del mouse.

  • Multitocco è un tocco che si verifica in più punti contemporaneamente. Windows 7 e WPF supportano l'input multitocco. Ogni volta che il tocco viene trattato nella documentazione relativa a WPF, i concetti illustrati si applicano al multitocco.

  • Si verifica una manipolazione quando il tocco viene interpretato come un'azione fisica applicata a un oggetto. In WPF gli eventi di manipolazione interpretano l'input come una manipolazione di traslazione, espansione o rotazione.

  • Un touch device rappresenta un dispositivo che produce un input tocco, ad esempio un singolo dito su un touchscreen.

Controlli che rispondono al tocco

È possibile scorrere i controlli seguenti trascinando un dito attraverso il controllo, se c'è contenuto non visualizzato.

ScrollViewerDefinisce la ScrollViewer.PanningMode proprietà associata che consente di specificare se il panning tocco è abilitato orizzontalmente, verticalmente, entrambi o nessuno dei due. La ScrollViewer.PanningDeceleration proprietà specifica la velocità con cui lo scorrimento rallenta quando l'utente solleva il dito dal touchscreen. La ScrollViewer.PanningRatio proprietà associata specifica il rapporto tra offset di scorrimento e offset di modifica della conversione.

Eventi di tocco

Le classi base, UIElement , UIElement3D e ContentElement , definiscono gli eventi che è possibile sottoscrivere, in modo che l'applicazione risponda al tocco. Gli eventi di tocco sono utili quando l'applicazione interpreta il tocco come qualcosa di diverso rispetto alla manipolazione di un oggetto. Un'applicazione che consente a un utente di disegnare con un dito o con più dita deve ad esempio sottoscrivere gli eventi di tocco.

Tutte tre le classi definiscono gli eventi seguenti, che hanno un comportamento simile, indipendentemente dalla classe che li definisce.

Analogamente agli eventi di tastiera e mouse, gli eventi di tocco sono eventi indirizzati. Gli eventi che iniziano con Preview sono eventi di tunneling e gli eventi che iniziano con Touch sono eventi di bubbling. Per altre informazioni sugli eventi indirizzati, vedere Cenni preliminari sugli eventi indirizzati. Quando si gestiscono questi eventi, è possibile ottenere la posizione dell'input, relativa a qualsiasi elemento, chiamando il GetTouchPoint metodo o GetIntermediateTouchPoints .

Per comprendere l'interazione tra gli eventi di tocco, si consideri lo scenario in cui un utente appoggia un dito su un elemento, muove il dito all'interno dell'elemento e quindi solleva il dito dall'elemento. La figura seguente illustra l'esecuzione degli eventi di bubbling. Gli eventi di tunneling vengono omessi per maggiore semplicità.

Sequenza degli eventi di tocco. Eventi di tocco

L'elenco seguente descrive la sequenza degli eventi della figura precedente.

  1. L' TouchEnter evento si verifica una volta quando l'utente inserisce un dito sull'elemento.

  2. L' TouchDown evento si verifica una volta.

  3. L' TouchMove evento si verifica più volte quando l'utente sposta il dito all'interno dell'elemento.

  4. L' TouchUp evento si verifica una volta quando l'utente solleva il dito dall'elemento.

  5. L' TouchLeave evento si verifica una volta.

Quando vengono usate più di due dita, gli eventi si verificano per ogni dito.

Eventi di manipolazione

Per i casi in cui un'applicazione consente a un utente di modificare un oggetto, la UIElement classe definisce gli eventi di manipolazione. A differenza degli eventi di tocco che segnalano semplicemente la posizione del tocco, gli eventi di manipolazione segnalano come può essere interpretato l'input. Ci sono tre tipi di manipolazioni: traslazione, espansione e rotazione. L'elenco seguente descrive come richiamare i tre tipi di manipolazioni.

  • Appoggiare un dito su un oggetto e muovere il dito sul touchscreen per richiamare una manipolazione di traslazione. Ciò comporta in genere lo spostamento dell'oggetto.

  • Appoggiare due dita su un oggetto e avvicinare o allontanare le dita tra loro per richiamare una manipolazione di espansione. Ciò comporta in genere il ridimensionamento dell'oggetto.

  • Appoggiare due dita su un oggetto e ruotare le dita una attorno all'altra per richiamare una manipolazione di rotazione. Ciò comporta in genere la rotazione dell'oggetto.

Si possono verificare più tipi di manipolazioni contemporaneamente.

Quando gli oggetti rispondono alle manipolazioni, si può fare in modo che sembrino avere un'inerzia. In questo modo, gli oggetti possono simulare il mondo fisico. Ad esempio se si spinge un libro su un tavolo con sufficiente forza, il libro continuerà a muoversi anche dopo che lo si lascia. WPF consente di simulare questo comportamento generando eventi di manipolazione dopo che le dita dell'utente rilasciano l'oggetto.

Per informazioni su come creare un'applicazione che consente all'utente di spostare, ridimensionare e ruotare un oggetto, vedere Procedura dettagliata: creazione della prima applicazione a tocco.

UIElementDefinisce gli eventi di manipolazione seguenti.

Per impostazione predefinita, un oggetto non UIElement riceve questi eventi di manipolazione. Per ricevere eventi di manipolazione su un oggetto UIElement , impostare su UIElement.IsManipulationEnabled true .

Percorso di esecuzione degli eventi di manipolazione

Si consideri uno scenario in cui un utente "lancia" un oggetto. L'utente appoggia un dito sull'oggetto, sposta il dito sul touchscreen per un breve tratto e quindi solleva il dito mentre l'oggetto si sta muovendo. Il risultato di questa azione è che l'oggetto si muoverà sotto il dito dell'utente e continuerà a muoversi dopo che l'utente ha sollevato il dito.

La figura seguente mostra il percorso di esecuzione degli eventi di manipolazione, con informazioni importanti relative a ogni evento.

Sequenza degli eventi di manipolazione. Eventi di manipolazione

L'elenco seguente descrive la sequenza degli eventi della figura precedente.

  1. L' ManipulationStarting evento si verifica quando l'utente posiziona un dito sull'oggetto. Tra le altre cose, questo evento consente di impostare la ManipulationContainer Proprietà. Negli eventi successivi la posizione della manipolazione sarà relativa a ManipulationContainer . In eventi diversi da ManipulationStarting questa proprietà è di sola lettura, pertanto l' ManipulationStarting evento è l'unica volta in cui è possibile impostare questa proprietà.

  2. L' ManipulationStarted evento si verifica successivamente. Questo evento segnala l'origine della manipolazione.

  3. L' ManipulationDelta evento si verifica più volte quando il dito di un utente si sposta su un touchscreen. La DeltaManipulation proprietà della ManipulationDeltaEventArgs classe indica se la manipolazione viene interpretata come spostamento, espansione o conversione. In questo contesto si esegue la maggior parte del lavoro di manipolazione di un oggetto.

  4. L' ManipulationInertiaStarting evento si verifica quando le dita dell'utente perdono il contatto con l'oggetto. Questo evento consente di specificare la decelerazione delle manipolazioni durante l'inerzia. In questo modo, l'oggetto può emulare spazi fisici o attribuiti diversi, se si desidera. Si supponga, ad esempio, che l'applicazione includa due oggetti che rappresentano elementi nel mondo fisico e che uno di questi sia più pesante dell'altro. È possibile fare in modo che l'oggetto più pesante rallenti più velocemente rispetto a quello più leggero.

  5. L' ManipulationDelta evento si verifica più volte durante l'inerzia. Si noti che questo evento si verifica quando le dita dell'utente si muovono sul touchscreen e quando WPF simula l'inerzia. In altre parole, ManipulationDelta si verifica prima e dopo l' ManipulationInertiaStarting evento. La ManipulationDeltaEventArgs.IsInertial proprietà indica se l' ManipulationDelta evento si verifica durante l'inerzia, quindi è possibile controllare tale proprietà ed eseguire azioni diverse, a seconda del valore.

  6. L' ManipulationCompleted evento si verifica quando la modifica e qualsiasi inerzia terminano. Ovvero, dopo che si sono ManipulationDelta verificati tutti gli eventi, l' ManipulationCompleted evento si verifica per segnalare che la manipolazione è stata completata.

UIElementDefinisce anche l' ManipulationBoundaryFeedback evento. Questo evento si verifica quando ReportBoundaryFeedback viene chiamato il metodo nell' ManipulationDelta evento. L' ManipulationBoundaryFeedback evento consente alle applicazioni o ai componenti di fornire feedback visivo quando un oggetto raggiunge un limite. Ad esempio, la Window classe gestisce l' ManipulationBoundaryFeedback evento per fare in modo che la finestra si sposti leggermente quando viene rilevato il bordo.

È possibile annullare la manipolazione chiamando il Cancel Metodo sugli argomenti dell'evento in qualsiasi evento di manipolazione eccetto l' ManipulationBoundaryFeedback evento. Quando si chiama Cancel , gli eventi di manipolazione non vengono più generati e si verificano gli eventi del mouse per il tocco. La tabella seguente descrive la relazione tra il momento in cui viene annullata la manipolazione e gli eventi del mouse che si verificano.

Evento su cui viene chiamato il metodo Cancel Eventi del mouse che si verificano per l'input già avvenuto
ManipulationStarting e ManipulationStarted Eventi di pressione del pulsante del mouse.
ManipulationDelta Eventi di pressione del pulsante e di spostamento del mouse.
ManipulationInertiaStarting e ManipulationCompleted Eventi di pressione e rilascio del pulsante e di spostamento del mouse.

Si noti che se si chiama Cancel quando la manipolazione è in inerzia, il metodo restituisce false e l'input non genera eventi del mouse.

Relazione tra eventi di tocco e di manipolazione

Un oggetto UIElement può sempre ricevere eventi di tocco. Quando la IsManipulationEnabled proprietà è impostata su true , un oggetto UIElement può ricevere sia eventi di tocco che di manipolazione. Se l' TouchDown evento non è gestito (ovvero la Handled proprietà è false ), la logica di manipolazione acquisisce il tocco sull'elemento e genera gli eventi di manipolazione. Se la Handled proprietà è impostata su true nell' TouchDown evento, la logica di manipolazione non genera eventi di manipolazione. La figura seguente mostra la relazione tra eventi di tocco ed eventi di manipolazione.

Relazione tra eventi di tocco e di manipolazione Eventi di tocco e manipolazione

L'elenco seguente descrive la relazione tra gli eventi di tocco e gli eventi di manipolazione illustrati nella figura precedente.

Focus

Ci sono due concetti principali relativi allo stato attivo in WPF: lo stato attivo della tastiera e lo stato attivo logico.

Stato attivo della tastiera

Lo stato attivo della tastiera fa riferimento all'elemento che riceve l'input dalla tastiera. Su un desktop può esserci un solo elemento con lo stato attivo della tastiera. In WPF l'elemento con lo stato attivo della tastiera sarà IsKeyboardFocused impostato su true . Il Keyboard metodo statico FocusedElement restituisce l'elemento che dispone attualmente dello stato attivo della tastiera.

Lo stato attivo della tastiera può essere ottenuto tramite tabulazione su un elemento o facendo clic sul mouse su determinati elementi, ad esempio TextBox . Lo stato attivo della tastiera può essere ottenuto anche a livello di programmazione tramite il Focus metodo nella Keyboard classe. Focus tenta di assegnare lo stato attivo della tastiera all'elemento specificato. L'elemento restituito da Focus è l'elemento che dispone attualmente dello stato attivo della tastiera.

Affinché un elemento ottenga lo stato attivo della tastiera Focusable , la proprietà e le IsVisible proprietà devono essere impostate su true. Alcune classi, ad esempio Panel , hanno Focusable impostato su per false impostazione predefinita; pertanto, potrebbe essere necessario impostare questa proprietà su true se si desidera che tale elemento possa ottenere lo stato attivo.

Nell'esempio seguente viene usato Focus per impostare lo stato attivo della tastiera su un oggetto Button . La posizione consigliata per impostare lo stato attivo iniziale in un'applicazione è nel Loaded gestore eventi.

private void OnLoaded(object sender, RoutedEventArgs e)
{
    // Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton);
}
Private Sub OnLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
    ' Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton)
End Sub

Per altre informazioni sullo stato attivo della tastiera, vedere Cenni preliminari sullo stato attivo.

Stato attivo logico

Lo stato attivo logico fa riferimento a FocusManager.FocusedElement in un ambito di stato attivo. In un'applicazione possono esserci più elementi con lo stato attivo logico, ma in un determinato ambito di stato attivo può esserci un solo elemento con lo stato attivo logico.

Un ambito di stato attivo è un elemento contenitore che tiene traccia del FocusedElement all'interno del relativo ambito. Quando lo stato attivo lascia un ambito di stato attivo, l'elemento con lo stato attivo perde lo stato attivo della tastiera, ma mantiene quello logico. Quando lo stato attivo torna nell'ambito di stato attivo, l'elemento con lo stato attivo ottiene nuovamente lo stato attivo della tastiera. In questo modo, lo stato attivo della tastiera può essere passato tra più ambiti, ma l'elemento con lo stato attivo in un determinato ambito rimane sicuramente tale al ritorno dello stato attivo.

Un elemento può essere trasformato in un ambito di stato attivo in impostando Extensible Application Markup Language (XAML) la FocusManager proprietà associata IsFocusScope su true o nel codice impostando la proprietà associata usando il SetIsFocusScope metodo.

Nell'esempio seguente viene StackPanel trasformato in un ambito di stato attivo impostando la IsFocusScope proprietà associata.

<StackPanel Name="focusScope1" 
            FocusManager.IsFocusScope="True"
            Height="200" Width="200">
  <Button Name="button1" Height="50" Width="50"/>
  <Button Name="button2" Height="50" Width="50"/>
</StackPanel>
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);
Dim focuseScope2 As New StackPanel()
FocusManager.SetIsFocusScope(focuseScope2, True)

WPFPer impostazione predefinita, le classi in cui sono gli ambiti di stato attivo sono Window ,, Menu ToolBar e ContextMenu .

Un elemento con lo stato attivo della tastiera avrà anche lo stato attivo logico per l'ambito di stato attivo a cui appartiene. Pertanto, l'impostazione dello stato attivo su un elemento con il Focus Metodo sulla Keyboard classe o sulle classi degli elementi di base tenterà di assegnare lo stato attivo della tastiera e lo stato attivo logico dell'elemento.

Per determinare l'elemento con stato attivo in un ambito di stato attivo, utilizzare GetFocusedElement . Per modificare l'elemento con stato attivo per un ambito di stato attivo, usare SetFocusedElement .

Per altre informazioni sullo stato attivo logico, vedere Cenni preliminari sullo stato attivo.

Posizione del mouse

L' WPF API di input fornisce informazioni utili per quanto riguarda gli spazi delle coordinate. Ad esempio, la coordinata (0,0) rappresenta la coordinata superiore sinistra, ma di quale elemento dell'albero? Si tratta dell'elemento che costituisce la destinazione dell'input? O dell'elemento a cui è associato il gestore eventi? Oppure di qualche altro elemento? Per evitare confusione, l' WPF API di input richiede di specificare il frame di riferimento quando si utilizzano le coordinate ottenute tramite il mouse. Il GetPosition metodo restituisce la coordinata del puntatore del mouse relativa all'elemento specificato.

Mouse Capture

I dispositivi di tipo mouse hanno una caratteristica modale specifica nota come mouse capture. Tale caratteristica viene usata per mantenere uno stato di input di transizione all'avvio di un'operazione di trascinamento della selezione, in modo che le altre operazioni che riguardano la posizione su schermo nominale del puntatore del mouse non vengano necessariamente eseguite. Durante il trascinamento, l'utente non può fare clic senza interrompere il trascinamento della selezione, quindi la maggior parte dei segnali di passaggio del mouse risulterà inappropriata quando l'origine del trascinamento mantiene lo stato mouse capture. Il sistema di input espone le API che possono determinare lo stato di acquisizione del mouse, nonché le API che possono forzare l'acquisizione del mouse su un elemento specifico o cancellare lo stato di acquisizione del mouse. Per altre informazioni sulle operazioni di trascinamento della selezione, vedere Cenni preliminari sul trascinamento della selezione.

Comandi

I comandi consentono la gestione dell'input a un livello più semantico rispetto all'input dei dispositivi. I comandi sono semplici direttive, come Cut, Copy, Paste o Open. I comandi sono utili per centralizzare la logica di comando. È possibile accedere allo stesso comando da un Menu , su ToolBar o tramite un tasto di scelta rapida. I comandi forniscono anche un meccanismo per disabilitare i controlli quando il comando non è più disponibile.

RoutedCommand è l' WPF implementazione di ICommand . Quando RoutedCommand viene eseguito un oggetto, un oggetto PreviewExecuted e un Executed evento vengono generati sulla destinazione del comando, che eseguono il tunneling e il bubbling attraverso l'albero degli elementi come altro input. Se non è impostata una destinazione del comando, questa sarà rappresentata dall'elemento con lo stato attivo della tastiera. La logica che esegue il comando è associata a un oggetto CommandBinding . Quando un Executed evento raggiunge un oggetto CommandBinding per il comando specifico, ExecutedRoutedEventHandler viene chiamato il metodo in CommandBinding . Il gestore esegue l'azione del comando.

Per altre informazioni sui comandi, vedere Cenni preliminari sull'esecuzione di comandi.

WPF fornisce una libreria di comandi comuni che comprende ApplicationCommands , MediaCommands , ComponentCommands , NavigationCommands e EditingCommands , oppure è possibile definirne di propri.

Nell'esempio seguente viene illustrato come configurare un oggetto MenuItem in modo che, quando si fa clic su di esso, richiami il Paste comando nell'oggetto TextBox , supponendo che TextBox abbia lo stato attivo della tastiera.

<StackPanel>
  <Menu>
    <MenuItem Command="ApplicationCommands.Paste" />
  </Menu>
  <TextBox />
</StackPanel>
// Creating the UI objects
StackPanel mainStackPanel = new StackPanel();
TextBox pasteTextBox = new TextBox();
Menu stackPanelMenu = new Menu();
MenuItem pasteMenuItem = new MenuItem();

// Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem);
mainStackPanel.Children.Add(stackPanelMenu);
mainStackPanel.Children.Add(pasteTextBox);

// Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste;

// Setting the command target to the TextBox
pasteMenuItem.CommandTarget = pasteTextBox;
' Creating the UI objects
Dim mainStackPanel As New StackPanel()
Dim pasteTextBox As New TextBox()
Dim stackPanelMenu As New Menu()
Dim pasteMenuItem As New MenuItem()

' Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem)
mainStackPanel.Children.Add(stackPanelMenu)
mainStackPanel.Children.Add(pasteTextBox)

' Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste

Per altre informazioni sui comandi in WPF, vedere Cenni preliminari sull'esecuzione di comandi.

Sistema di input ed elementi di base

Gli eventi di input come gli eventi associati definiti dalle Mouse Keyboard classi, e Stylus vengono generati dal sistema di input e inseriti in una determinata posizione nel modello a oggetti in base all'hit test della struttura ad albero visuale in fase di esecuzione.

Ogni evento che Mouse , Keyboard e Stylus definiscono come un evento associato viene anche nuovamente esposto dalle classi degli elementi di base UIElement e ContentElement come nuovo evento indirizzato. Gli eventi indirizzati degli elementi di base vengono generati da classi che gestiscono l'evento associato originale e riutilizzano i dati dell'evento.

Quando l'evento di input viene associato a un particolare elemento di origine tramite l'implementazione dell'evento di input dei relativi elementi di base, può essere indirizzato lungo la parte restante della route di un evento basata su una combinazione di oggetti albero logico e struttura ad albero visuale ed essere gestito dal codice dell'applicazione. In genere, è più facile gestire questi eventi di input correlati al dispositivo usando gli eventi indirizzati in UIElement e ContentElement , perché è possibile usare una sintassi del gestore eventi più intuitiva sia in XAML che nel codice. È possibile scegliere di gestire invece l'evento associato che ha avviato il processo, ma potrebbero sorgere diversi problemi: l'evento associato potrebbe essere contrassegnato come gestito dalla gestione della classe dell'elemento di base, per cui potrebbe essere necessario usare i metodi della funzione di accesso invece della sintassi dell'evento vera e propria per associare i gestori per gli eventi associati.

Passaggi successivi

A questo punto si conoscono diverse tecniche per la gestione dell'input in WPF. Si dovrebbe anche avere una conoscenza più approfondita dei vari tipi di eventi di input e dei meccanismi degli eventi indirizzati usati in WPF.

Sono disponibili risorse aggiuntive che illustrano più dettagliatamente gli elementi del framework WPF e il routing degli eventi. Per altre informazioni generali, vedere Cenni preliminari sull'esecuzione di comandi, Cenni preliminari sullo stato attivo, Cenni preliminari sugli elementi di base, Strutture ad albero in WPF e Cenni preliminari sugli eventi indirizzati.

Vedi anche