Accessibilità tramite tastiera

Se l'app non fornisce un buon accesso tramite tastiera, gli utenti non vedenti o che hanno problemi di mobilità possono avere difficoltà a usare l'app o potrebbero non essere in grado di usarla affatto.

Spostamento tramite tastiera tra gli elementi dell'interfaccia utente

Per usare la tastiera con un controllo, il controllo deve avere lo stato attivo e per ricevere lo stato attivo (senza usare un puntatore) il controllo deve essere accessibile in una progettazione dell'interfaccia utente tramite lo spostamento tramite tabulazione. Per impostazione predefinita, l'ordine di tabulazione dei controlli corrisponde all'ordine in cui vengono aggiunti a un'area di progettazione, elencati in XAML o aggiunti a livello di codice a un contenitore.

Nella maggior parte dei casi, l'ordine predefinito in base alla modalità di definizione dei controlli in XAML è l'ordine migliore, soprattutto perché questo è l'ordine in cui i controlli vengono letti dalle utilità per la lettura dello schermo. Tuttavia, l'ordine predefinito non corrisponde necessariamente all'ordine visivo. La posizione di visualizzazione effettiva può dipendere dal contenitore di layout padre e da determinate proprietà che è possibile impostare sugli elementi figlio per influenzare il layout. Per assicurarsi che l'app abbia un buon ordine di tabulazioni, testare questo comportamento manualmente. Soprattutto se hai una metafora griglia o una metafora di tabella per il layout, l'ordine in cui gli utenti potrebbero leggere rispetto all'ordine di tabulazione potrebbe finire diverso. Questo non è sempre un problema in e di se stesso. Tuttavia, assicurati di testare le funzionalità della tua app sia come interfaccia utente toccabile che come interfaccia utente accessibile tramite tastiera e verificare che l'interfaccia utente abbia senso in entrambi i modi.

Puoi fare in modo che l'ordine di tabulazione corrisponda all'ordine visivo modificando il codice XAML. In alternativa, è possibile eseguire l'override dell'ordine di tabulazione predefinito impostando la proprietà TabIndex, come illustrato nell'esempio seguente di un layout Grid che usa lo spostamento tramite tabulazione a colonne.

XAML

<!--Custom tab order.-->
<Grid>
  <Grid.RowDefinitions>...</Grid.RowDefinitions>
  <Grid.ColumnDefinitions>...</Grid.ColumnDefinitions>

  <TextBlock Grid.Column="1" HorizontalAlignment="Center">Groom</TextBlock>
  <TextBlock Grid.Column="2" HorizontalAlignment="Center">Bride</TextBlock>

  <TextBlock Grid.Row="1">First name</TextBlock>
  <TextBox x:Name="GroomFirstName" Grid.Row="1" Grid.Column="1" TabIndex="1"/>
  <TextBox x:Name="BrideFirstName" Grid.Row="1" Grid.Column="2" TabIndex="3"/>

  <TextBlock Grid.Row="2">Last name</TextBlock>
  <TextBox x:Name="GroomLastName" Grid.Row="2" Grid.Column="1" TabIndex="2"/>
  <TextBox x:Name="BrideLastName" Grid.Row="2" Grid.Column="2" TabIndex="4"/>
</Grid>

È possibile escludere un controllo dall'ordine di tabulazioni. Questa operazione viene in genere eseguita solo impostando la proprietà IsEnabled su false. Un controllo disabilitato viene escluso automaticamente dall'ordine di tabulazioni. Ma occasionalmente potresti voler escludere un controllo dall'ordine di tabulazioni anche se non è disabilitato. In questo caso, è possibile impostare la proprietà IsTabStop su false.

Tutti gli elementi che possono avere lo stato attivo sono in genere nell'ordine di tabulazione per impostazione predefinita. L'eccezione è che alcuni tipi di visualizzazione del testo, ad esempio RichTextBlock , possono avere lo stato attivo in modo che possano essere accessibili dagli Appunti per la selezione del testo. Tuttavia, non si trovano nell'ordine di tabulazione perché non è previsto che gli elementi di testo statici siano nell'ordine di tabulazione. Non sono convenzionalmente interattive (non possono essere richiamate e non richiedono input di testo, ma supportano il pattern di controllo Text che supporta la ricerca e la regolazione dei punti di selezione nel testo). Il testo non deve avere la connotazione che imposta lo stato attivo su di esso consentirà un'azione possibile. Gli elementi di testo verranno comunque rilevati da assistive technology e letti ad alta voce nelle utilità per la lettura dello schermo, ma che si basano su tecniche diverse dalla ricerca di tali elementi nell'ordine di tabulazione pratico.

Se si modificano i valori TabIndex o si usa l'ordine predefinito, si applicano queste regole:

  • Se TabIndex non è impostato su un elemento, il valore predefinito usato è Int32.MaxValue e l'ordine di tabulazione è basato sull'ordine di dichiarazione nelle raccolte XAML o figlio.
  • Se TabIndex è impostato su un elemento:
    • Gli elementi dell'interfaccia utente con TabIndex uguale a 0 vengono aggiunte all'ordine di tabulazione in base all'ordine di dichiarazione in XAML o nelle raccolte figlio.
    • Gli elementi dell'interfaccia utente con TabIndex maggiore di 0 vengono aggiunti all'ordine di tabulazioni in base al valore TabIndex.
    • Gli elementi dell'interfaccia utente con TabIndex minore di 0 vengono aggiunte all'ordine di tabulazione e vengono visualizzate prima di qualsiasi valore zero. Ciò è potenzialmente diverso dalla gestione html dell'attributo tabindex (e tabindex negativo non è supportato nelle specifiche HTML precedenti).

Ad esempio, il frammento di codice seguente mostra una raccolta di elementi con impostazioni TabIndex variabili (B viene assegnato il valore di Int32.MaxValue o 2.147.483.647).

<StackPanel Background="#333">
  <StackPanel Background="#FF33FF">
    <Button>A</Button>
    <Button TabIndex="2147483647">B</Button>
    <Button>C</Button>
  </StackPanel>
  <StackPanel Background="#33FFFF">
    <Button TabIndex="1">D</Button>
    <Button TabIndex="1">E</Button>
    <Button TabIndex="0">F</Button>
  </StackPanel>
</StackPanel>

Ciò si traduce nel seguente ordine di tabulazione:

  1. F
  2. D
  3. E
  4. Un
  5. B
  6. A

Spostamento tramite tastiera all'interno di un elemento dell'interfaccia utente

Per gli elementi compositi, è importante garantire una corretta navigazione interna tra gli elementi contenuti. Un elemento composito può gestire il figlio attivo corrente per ridurre il sovraccarico di avere tutti gli elementi figlio in grado di avere lo stato attivo. Tale elemento composito è incluso nell'ordine di tabulazioni e gestisce gli eventi di spostamento tramite tastiera stessi. Molti dei controlli compositi dispongono già di una logica di spostamento interna integrata nella gestione degli eventi del controllo. Ad esempio, l'attraversamento con tasti di direzione degli elementi è abilitato per impostazione predefinita nei controlli ListView, GridView, ListBox e FlipView.

Alternative della tastiera alle azioni e agli eventi del puntatore per elementi di controllo specifici

Assicurarsi che gli elementi dell'interfaccia utente su cui è possibile fare clic possano essere richiamati anche tramite la tastiera. Per usare la tastiera con un elemento dell'interfaccia utente, l'elemento deve avere lo stato attivo. Solo le classi che derivano da Control supportano lo stato attivo e lo spostamento tramite tabulazione.

Per gli elementi dell'interfaccia utente che possono essere richiamati, implementare i gestori eventi della tastiera per la barra spaziatrice e i tasti INVIO. In questo modo il supporto dell'accessibilità tramite tastiera di base è completo e consente agli utenti di eseguire scenari di app di base usando solo la tastiera; ovvero gli utenti possono raggiungere tutti gli elementi interattivi dell'interfaccia utente e attivare la funzionalità predefinita.

Nei casi in cui un elemento che vuoi usare nell'interfaccia utente non può avere lo stato attivo, puoi creare un controllo personalizzato. È necessario impostare la proprietà IsTabStop su true per abilitare lo stato attivo ed è necessario fornire un'indicazione visiva dello stato attivo creando uno stato visivo che decora l'interfaccia utente con un indicatore di stato attivo. Tuttavia, spesso è più facile usare la composizione dei controlli in modo che il supporto per tabulazioni, stato attivo e Microsoft Automazione interfaccia utente peer e pattern vengano gestiti dal controllo in cui si sceglie di comporre il contenuto.

Ad esempio, invece di gestire un evento premuto dal puntatore in un'immagine, è possibile eseguire il wrapping di tale elemento in un controllo Button per ottenere il supporto di puntatore, tastiera e stato attivo.

XAML

<!--Don't do this.-->
<Image Source="sample.jpg" PointerPressed="Image_PointerPressed"/>

<!--Do this instead.-->
<Button Click="Button_Click"><Image Source="sample.jpg"/></Button>

Scelte rapide da tastiera

Oltre a implementare lo spostamento tramite tastiera e l'attivazione per l'app, è consigliabile implementare i tasti di scelta rapida per le funzionalità dell'app. Lo spostamento tramite tabulazioni offre un buon livello di supporto della tastiera, ma con moduli complessi che è possibile aggiungere anche il supporto per i tasti di scelta rapida. Ciò può rendere l'applicazione più efficiente da usare, anche per gli utenti che usano sia una tastiera che un dispositivo di puntamento.

Un tasto di scelta rapida è una combinazione di tastiera che migliora la produttività fornendo un modo efficiente per consentire all'utente di accedere alle funzionalità dell'app. Ci sono due tipi di scorciatoie:

  • Un tasto di scelta è un collegamento a una parte dell'interfaccia utente nell'app. I tasti di scelta sono costituiti dal tasto ALT e da un tasto lettera.
  • Un tasto di scelta rapida è un collegamento a un comando dell'app. La tua app potrebbe avere o meno un'interfaccia utente che corrisponde esattamente al comando. I tasti di scelta rapida sono costituiti dal tasto CTRL e da un tasto lettera.

È fondamentale fornire un modo semplice per gli utenti che si basano sulle utilità per la lettura dello schermo e altre tecnologie di assistive technology per individuare i tasti di scelta rapida dell'app. Comunicare i tasti di scelta rapida usando descrizioni comandi, nomi accessibili, descrizioni accessibili o altre forme di comunicazione sullo schermo. Come minimo, i tasti di scelta rapida devono essere ben documentati nel contenuto della Guida dell'app.

È possibile documentare i tasti di scelta tramite utilità per la lettura dello schermo impostando la proprietà associata AutomationProperties.AccessKey su una stringa che descrive il tasto di scelta rapida. Esiste anche una proprietà associata AutomationProperties.AcceleratorKey per documentare i tasti di scelta rapida non mnemonici, anche se le utilità per la lettura dello schermo trattano in genere entrambe le proprietà allo stesso modo. Provare a documentare i tasti di scelta rapida in diversi modi, usando descrizioni comando, proprietà di automazione e documentazione della Guida scritta.

Nell'esempio seguente viene illustrato come documentare i tasti di scelta rapida per i pulsanti di riproduzione multimediale, sospensione e arresto.

XAML

<Grid KeyDown="Grid_KeyDown">

  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>

  <MediaElement x:Name="DemoMovie" Source="xbox.wmv"
    Width="500" Height="500" Margin="20" HorizontalAlignment="Center" />

  <StackPanel Grid.Row="1" Margin="10"
    Orientation="Horizontal" HorizontalAlignment="Center">

    <Button x:Name="PlayButton" Click="MediaButton_Click"
      ToolTipService.ToolTip="Shortcut key: Ctrl+P"
      AutomationProperties.AcceleratorKey="Control P">
      <TextBlock>Play</TextBlock>
    </Button>

    <Button x:Name="PauseButton" Click="MediaButton_Click"
      ToolTipService.ToolTip="Shortcut key: Ctrl+A"
      AutomationProperties.AcceleratorKey="Control A">
      <TextBlock>Pause</TextBlock>
    </Button>

    <Button x:Name="StopButton" Click="MediaButton_Click"
      ToolTipService.ToolTip="Shortcut key: Ctrl+S"
      AutomationProperties.AcceleratorKey="Control S">
      <TextBlock>Stop</TextBlock>
    </Button>
  </StackPanel>
</Grid>

Importante

L'impostazione di AutomationProperties.AcceleratorKey o AutomationProperties.AccessKey non abilita la funzionalità della tastiera. Segnala solo al framework Automazione interfaccia utente quali chiavi devono essere usate, in modo che tali informazioni possano essere passate agli utenti tramite assistive technology. L'implementazione per la gestione delle chiavi deve comunque essere eseguita nel codice, non nel codice XAML. Dovrai comunque collegare i gestori per gli eventi KeyDown o KeyUp sul controllo pertinente per implementare effettivamente il comportamento dei tasti di scelta rapida nell'app. Inoltre, la decorazione del testo sottolineato per un tasto di scelta non viene fornita automaticamente. È necessario sottolineare in modo esplicito il testo per la chiave specifica nel tasto mnemonico come formattazione sottolineatura inline se si desidera visualizzare il testo sottolineato nell'interfaccia utente.

Per semplicità, l'esempio precedente omette l'uso di risorse per stringhe come "CTRL+A". Tuttavia, è necessario prendere in considerazione anche i tasti di scelta rapida durante la localizzazione. La localizzazione dei tasti di scelta rapida è rilevante perché la scelta del tasto da usare come tasto di scelta rapida dipende in genere dall'etichetta di testo visibile per l'elemento.

Per altre indicazioni sull'implementazione dei tasti di scelta rapida, vedere Tasti di scelta rapida nelle Linee guida per l'interazione dell'esperienza utente di Windows.

Implementazione di un gestore eventi della chiave

Gli eventi di input, ad esempio gli eventi chiave, usano un concetto di evento denominato eventi indirizzati. Un evento indirizzato può scorrere gli elementi figlio di un controllo composito, in modo che un padre di controllo comune possa gestire eventi per più elementi figlio. Questo modello di evento è utile per definire le azioni dei tasti di scelta rapida per un controllo che contiene diverse parti composite che per progettazione non possono avere lo stato attivo o far parte dell'ordine di tabulazione.

Ad esempio di codice che mostra come scrivere un gestore eventi di tasti che include il controllo della presenza di modificatori, ad esempio il tasto CTRL, vedere Interazioni con tastiera.

Spostamento tramite tastiera per i controlli personalizzati

È consigliabile usare i tasti di direzione come tasti di scelta rapida per spostarsi tra gli elementi figlio, nei casi in cui gli elementi figlio hanno una relazione speciale tra loro. Se i nodi della visualizzazione albero hanno sottoelementi separati per la gestione dell'attivazione di espansione e compressione dei nodi, usare i tasti freccia sinistra e destra per fornire la funzionalità di espansione della tastiera. Se si dispone di un controllo orientato che supporta l'attraversamento direzionale all'interno del contenuto del controllo, usare i tasti di direzione appropriati.

In genere si implementa la gestione delle chiavi personalizzata per i controlli personalizzati includendo un override dei metodi OnKeyDown e OnKeyUp come parte della logica della classe.

Esempio di stato di visualizzazione per un indicatore di stato attivo

Abbiamo accennato in precedenza che qualsiasi controllo personalizzato che consente all'utente di concentrarsi deve avere un indicatore di stato attivo visivo. In genere l'indicatore di stato attivo è semplice come disegnare una forma rettangolo immediatamente intorno al rettangolo di delimitazione normale del controllo. Rectangle per lo stato attivo visivo è un elemento peer del resto della composizione del controllo in un modello di controllo, ma inizialmente viene impostato con un valore Visibility di Collapsed perché il controllo non è ancora attivo. Quindi, quando il controllo ottiene lo stato attivo, viene richiamato uno stato di visualizzazione che imposta in modo specifico la visibilità dell'oggetto visivo dello stato attivo su Visible. Una volta spostato lo stato attivo altrove, viene chiamato un altro stato di visualizzazione e la proprietà Visibility diventa Collapsed.

Tutti i controlli XAML predefiniti visualizzeranno un indicatore di stato attivo visivo appropriato quando è attivo (se possono essere attivati). Esistono anche un aspetto potenzialmente diverso a seconda del tema selezionato dell'utente (in particolare se l'utente usa una modalità a contrasto elevato). Se usi i controlli XAML nell'interfaccia utente e non sostituisci i modelli di controllo, non devi eseguire alcuna operazione aggiuntiva per ottenere indicatori di stato attivo visivo sui controlli che si comportano e visualizzano correttamente. Tuttavia, se intendi ripetere un controllo o se sei curioso di come i controlli XAML forniscono i relativi indicatori di stato attivo visivo, la parte restante di questa sezione spiega come viene eseguita in XAML e nella logica del controllo.

Ecco un esempio di XAML proveniente dal modello XAML predefinito per un pulsante.

XAML

<ControlTemplate TargetType="Button">
...
    <Rectangle
      x:Name="FocusVisualWhite"
      IsHitTestVisible="False"
      Stroke="{ThemeResource FocusVisualWhiteStrokeThemeBrush}"
      StrokeEndLineCap="Square"
      StrokeDashArray="1,1"
      Opacity="0"
      StrokeDashOffset="1.5"/>
    <Rectangle
      x:Name="FocusVisualBlack"
      IsHitTestVisible="False"
      Stroke="{ThemeResource FocusVisualBlackStrokeThemeBrush}"
      StrokeEndLineCap="Square"
      StrokeDashArray="1,1"
      Opacity="0"
      StrokeDashOffset="0.5"/>
...
</ControlTemplate>

Finora questa è solo la composizione. Per controllare la visibilità dell'indicatore di stato attivo, definisci gli stati visivi che attivano o disattivano la proprietà Visibility. Questa operazione viene eseguita usando la proprietà associata VisualStateManager e VisualStateManager.VisualStateGroups, come applicato all'elemento radice che definisce la composizione.

XAML

<ControlTemplate TargetType="Button">
  <Grid>
    <VisualStateManager.VisualStateGroups>
       <!--other visual state groups here-->
       <VisualStateGroup x:Name="FocusStates">
         <VisualState x:Name="Focused">
           <Storyboard>
             <DoubleAnimation
               Storyboard.TargetName="FocusVisualWhite"
               Storyboard.TargetProperty="Opacity"
               To="1" Duration="0"/>
             <DoubleAnimation
               Storyboard.TargetName="FocusVisualBlack"
               Storyboard.TargetProperty="Opacity"
               To="1" Duration="0"/>
         </VisualState>
         <VisualState x:Name="Unfocused" />
         <VisualState x:Name="PointerFocused" />
       </VisualStateGroup>
     <VisualStateManager.VisualStateGroups>
<!--composition is here-->
   </Grid>
</ControlTemplate>

Si noti che solo uno degli stati denominati regola direttamente Visibility , mentre gli altri sono apparentemente vuoti. Il modo in cui gli stati di visualizzazione funzionano è che non appena il controllo utilizza un altro stato dello stesso VisualStateGroup, tutte le animazioni applicate dallo stato precedente vengono immediatamente annullate. Poiché l'impostazione predefinita Visibilità dalla composizione è Collapsed, significa che il rettangolo non verrà visualizzato. La logica di controllo controlla questo aspetto ascoltando eventi di stato attivo come GotFocus e modificando gli stati con GoToState. Spesso questo è già gestito automaticamente se si usa un controllo predefinito o si personalizza in base a un controllo che ha già tale comportamento.

Accessibilità tramite tastiera e Windows Telefono

Un dispositivo Windows Telefono in genere non dispone di una tastiera hardware dedicata. Tuttavia, un pannello SIP (Soft Input Panel) può supportare diversi scenari di accessibilità tramite tastiera. Le utilità per la lettura dello schermo possono leggere l'input di testo dal sip di testo , inclusa l'annuncio delle eliminazioni. Gli utenti possono scoprire dove si trovano le dita perché l'utilità per la lettura dello schermo può rilevare che l'utente sta analizzando i tasti e legge ad alta voce il nome della chiave analizzata. Inoltre, alcuni dei concetti di accessibilità orientata alla tastiera possono essere mappati a comportamenti di assistive technology correlati che non usano affatto una tastiera. Ad esempio, anche se un SIP non include un tasto TAB, l'Assistente vocale supporta un movimento tocco equivalente a premere TAB, quindi avere un ordine di tabulazione utile attraverso i controlli in un'interfaccia utente è ancora un importante principio di accessibilità. I tasti di direzione usati per spostarsi tra le parti all'interno di controlli complessi sono supportati anche tramite i movimenti tocco dell'Assistente vocale. Dopo che lo stato attivo ha raggiunto un controllo che non è per l'input di testo, Assistente vocale supporta un movimento che richiama l'azione del controllo.

I tasti di scelta rapida non sono in genere rilevanti per le app di Windows Telefono, perché un SIP non include i tasti Di controllo o ALT.

Esempi

Suggerimento

L'app Raccolta WinUI 3 include esempi interattivi della maggior parte dei controlli e delle funzionalità di WinUI 3. Scaricare l'app da Microsoft Store od ottenere il codice sorgente su GitHub