Navigation focus pour le clavier, le boîtier de commande, le contrôle à distance et les outils d’accessibilité

Clavier, distant et pavé D

Utilisez la navigation focus pour fournir des expériences d’interaction complètes et cohérentes dans vos applications Windows et des contrôles personnalisés pour les utilisateurs de l’alimentation du clavier, ceux présentant des handicaps et d’autres exigences d’accessibilité, ainsi que l’expérience de 10 pieds des écrans de télévision et xbox One.

Vue d’ensemble

La navigation focus fait référence au mécanisme sous-jacent qui permet aux utilisateurs de naviguer et d’interagir avec l’interface utilisateur d’une application Windows à l’aide d’un clavier, d’un boîtier de commande ou d’un contrôle à distance.

Remarque

Les appareils d’entrée sont généralement classés comme des appareils pointants, tels que le pavé tactile, le stylet et la souris, et les appareils sans pointage, tels que le clavier, le boîtier de commande et le contrôle à distance.

Cette rubrique explique comment optimiser une application Windows et créer des expériences d’interaction personnalisées pour les utilisateurs qui s’appuient sur des types d’entrée non pointants.

Même si nous nous concentrons sur l’entrée du clavier pour les contrôles personnalisés dans les applications Windows sur les PC, une expérience de clavier bien conçue est également importante pour les claviers logiciels tels que le clavier tactile et le clavier visuel (OSK), prenant en charge les outils d’accessibilité tels que le Narrateur Windows et prenant en charge l’expérience de 10 pieds.

Consultez Gérer les entrées de pointeur pour obtenir des conseils sur la création d’expériences personnalisées dans les applications Windows pour pointer des appareils.

Pour plus d’informations générales sur la création d’applications et d’expériences pour le clavier, consultez Interaction au clavier.

Règle générale

Seuls les éléments d’interface utilisateur qui nécessitent une interaction utilisateur doivent prendre en charge la navigation au focus, les éléments qui ne nécessitent pas d’action, comme les images statiques, n’ont pas besoin du focus clavier. Les lecteurs d’écran et les outils d’accessibilité similaires annoncent toujours ces éléments statiques, même s’ils ne sont pas inclus dans la navigation focus.

Il est important de se rappeler que contrairement à la navigation avec un appareil pointeur tel qu’une souris ou une touche tactile, la navigation focus est linéaire. Lors de l’implémentation de la navigation focus, réfléchissez à la façon dont un utilisateur interagit avec votre application et à ce que doit être la navigation logique. Dans la plupart des cas, nous vous recommandons de suivre le comportement de navigation focus personnalisé suivant le modèle de lecture préféré de la culture de l’utilisateur.

Voici quelques autres considérations relatives à la navigation axée sur le focus :

  • Les contrôles sont-ils regroupés logiquement ?
  • Existe-t-il des groupes de contrôles avec une plus grande importance ?
    • Si oui, ces groupes contiennent-ils des sous-groupes ?
  • La disposition nécessite-t-elle une navigation directionnelle personnalisée (touches de direction) et un ordre de tabulation ?

Le livre électronique Engineering Software for Accessibility a un excellent chapitre sur la conception de la hiérarchie logique.

Navigation directionnelle 2D pour le clavier

La région de navigation interne 2D d’un contrôle ou d’un groupe de contrôles est appelée « zone directionnelle ». Lorsque le focus se déplace vers cet objet, les touches de direction du clavier (gauche, droite, haut et bas) peuvent être utilisées pour naviguer entre les éléments enfants dans la zone directionnelle.

zone directionnelleRégion de navigation interne 2D ou zone directionnelle d’un groupe de contrôles

Vous pouvez utiliser la propriété XYFocusKeyboardNavigation (qui a des valeurs possibles d’Auto, Enabled ou Disabled) pour gérer la navigation interne 2D avec les touches de direction clavier.

Remarque

L’ordre de tabulation n’est pas affecté par cette propriété. Pour éviter une expérience de navigation déroutante, nous vous recommandons de ne pas spécifier explicitement les éléments enfants d’une zone directionnelle dans l’ordre de navigation tabulation de votre application. Pour plus d’informations sur le comportement de tabulation d’un élément, consultez les propriétés UIElement.TabFocusNavigation et TabIndex .

Auto (comportement par défaut)

Lorsqu’il est défini sur Auto, le comportement de navigation directionnelle est déterminé par l’ancêtre de l’élément ou la hiérarchie d’héritage. Si tous les ancêtres sont en mode par défaut (défini sur Auto), la navigation directionnelle avec le clavier n’est pas prise en charge.

Disabled

Définissez XYFocusKeyboardNavigation sur Disabled pour bloquer la navigation directionnelle sur le contrôle et ses éléments enfants.

Comportement désactivé de XYFocusKeyboardNavigationComportement désactivé de XYFocusKeyboardNavigation

Dans cet exemple, le StackPanel principal (ContainerPrimary) a XYFocusKeyboardNavigation défini sur Activé. Tous les éléments enfants héritent de ce paramètre et peuvent être redirigés avec les touches de direction. Toutefois, les éléments B3 et B4 se trouvent dans un StackPanel secondaire (ContainerSecondary) avec XYFocusKeyboardNavigation défini sur Disabled, qui remplace le conteneur principal et désactive la navigation par touche de direction vers lui-même et entre ses éléments enfants.

<Grid 
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" 
    TabFocusNavigation="Cycle">
    <Grid.RowDefinitions>
        <RowDefinition Height="40"/>
        <RowDefinition Height="75"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <TextBlock Name="KeyPressed"
                Grid.Row="0" 
                FontWeight="ExtraBold" 
                HorizontalTextAlignment="Center"
                TextWrapping="Wrap" 
                Padding="10" />
    <StackPanel Name="ContainerPrimary" 
                XYFocusKeyboardNavigation="Enabled" 
                KeyDown="ContainerPrimary_KeyDown" 
                Orientation="Horizontal" 
                BorderBrush="Green" 
                BorderThickness="2" 
                Grid.Row="1" 
                Padding="10" 
                MaxWidth="200">
        <Button Name="B1" 
                Content="B1" 
                GettingFocus="Btn_GettingFocus" />
        <Button Name="B2" 
                Content="B2" 
                GettingFocus="Btn_GettingFocus" />
        <StackPanel Name="ContainerSecondary" 
                    XYFocusKeyboardNavigation="Disabled" 
                    Orientation="Horizontal" 
                    BorderBrush="Red" 
                    BorderThickness="2">
            <Button Name="B3" 
                    Content="B3" 
                    GettingFocus="Btn_GettingFocus" />
            <Button Name="B4" 
                    Content="B4" 
                    GettingFocus="Btn_GettingFocus" />
        </StackPanel>
    </StackPanel>
</Grid>

Activé

Définissez XYFocusKeyboardNavigation sur Activé pour prendre en charge la navigation directionnelle 2D sur un contrôle et chacun de ses objets enfants UIElement.

Lorsque cette option est définie, la navigation avec les touches de direction est limitée aux éléments de la zone directionnelle. La navigation par onglet n’est pas affectée, car tous les contrôles restent accessibles via leur hiérarchie d’ordre de tabulation.

Comportement XYFocusKeyboardNavigation activéComportement XYFocusKeyboardNavigation activé

Dans cet exemple, le StackPanel principal (ContainerPrimary) a XYFocusKeyboardNavigation défini sur Activé. Tous les éléments enfants héritent de ce paramètre et peuvent être redirigés avec les touches de direction. Les éléments B3 et B4 se trouvent dans un StackPanel secondaire (ContainerSecondary) où XYFocusKeyboardNavigation n’est pas défini, qui hérite ensuite du paramètre de conteneur principal. L’élément B5 ne se trouve pas dans une zone directionnelle déclarée et ne prend pas en charge la navigation par touches de direction, mais prend en charge le comportement de navigation par onglet standard.

<Grid
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    TabFocusNavigation="Cycle">
    <Grid.RowDefinitions>
        <RowDefinition Height="40"/>
        <RowDefinition Height="100"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <TextBlock Name="KeyPressed"
               Grid.Row="0"
               FontWeight="ExtraBold"
               HorizontalTextAlignment="Center"
               TextWrapping="Wrap"
               Padding="10" />
    <StackPanel Grid.Row="1"
                Orientation="Horizontal"
                HorizontalAlignment="Center">
        <StackPanel Name="ContainerPrimary"
                    XYFocusKeyboardNavigation="Enabled"
                    KeyDown="ContainerPrimary_KeyDown"
                    Orientation="Horizontal"
                    BorderBrush="Green"
                    BorderThickness="2"
                    Padding="5" Margin="5">
            <Button Name="B1"
                    Content="B1"
                    GettingFocus="Btn_GettingFocus" Margin="5" />
            <Button Name="B2"
                    Content="B2"
                    GettingFocus="Btn_GettingFocus" />
            <StackPanel Name="ContainerSecondary"
                        Orientation="Horizontal"
                        BorderBrush="Red"
                        BorderThickness="2"
                        Margin="5">
                <Button Name="B3"
                        Content="B3"
                        GettingFocus="Btn_GettingFocus"
                        Margin="5" />
                <Button Name="B4"
                        Content="B4"
                        GettingFocus="Btn_GettingFocus"
                        Margin="5" />
            </StackPanel>
        </StackPanel>
        <Button Name="B5"
                Content="B5"
                GettingFocus="Btn_GettingFocus"
                Margin="5" />
    </StackPanel>
</Grid>

Vous pouvez avoir plusieurs niveaux de zones directionnelles imbriquées. Si tous les éléments parents ont XYFocusKeyboardNavigation défini sur Activé, les limites de la région de navigation interne sont ignorées.

Voici un exemple de deux zones directionnelles imbriquées au sein d’un élément qui ne prend pas explicitement en charge la navigation directionnelle 2D. Dans ce cas, la navigation directionnelle n’est pas prise en charge entre les deux zones imbriquées.

Comportement XYFocusKeyboardNavigation activé et imbriquéComportement XYFocusKeyboardNavigation activé et imbriqué

Voici un exemple plus complexe de trois zones directionnelles imbriquées où :

  • Lorsque B1 a le focus, seul B5 peut être accédé à (et vice versa) car il existe une limite de zone directionnelle où XYFocusKeyboardNavigation est défini sur Désactivé, rendant B2, B3 et B4 inaccessible avec les touches de direction
  • Lorsque B2 a le focus, seul B3 peut être accédé à (et vice versa) car la limite de zone directionnelle empêche la navigation de touches de direction vers B1, B4 et B5
  • Lorsque B4 a le focus, la touche Tab doit être utilisée pour naviguer entre les contrôles

Comportement imbriqué XYFocusKeyboardNavigation activé et complexe

Comportement imbriqué XYFocusKeyboardNavigation activé et complexe

Navigation dans les onglets

Bien que les touches de direction puissent être utilisées pour la navigation directionnelle 2D witin un contrôle ou un groupe de contrôles, la touche Tab peut être utilisée pour naviguer entre tous les contrôles d’une application Windows.

Tous les contrôles interactifs prennent en charge la navigation par touche Tab par défaut (propriété IsEnabled et IsTabStop true), avec l’ordre de tabulation logique dérivé de la disposition du contrôle dans votre application. Toutefois, l’ordre par défaut ne correspond pas nécessairement à l’ordre visuel. La position d’affichage réelle peut dépendre du conteneur de disposition parent et de certaines propriétés que vous pouvez définir sur les éléments enfants pour influencer la disposition.

Évitez de définir un ordre de tabulation personnalisé dans lequel le focus se déplace de manière aléatoire dans votre application. Par exemple, une liste de contrôles dans un formulaire doit avoir un ordre de tabulation qui va de haut en bas et de gauche à droite (en fonction des paramètres régionaux).

Dans cette section, nous décrivons comment cet ordre de tabulation peut être entièrement personnalisé pour répondre à votre application.

Définir le comportement de navigation des onglets

La propriété TabFocusNavigation de UIElement spécifie le comportement de navigation des onglets pour toute l’arborescence d’objets (ou zone directionnelle).

Remarque

Utilisez cette propriété au lieu de la propriété Control.TabNavigation pour les objets qui n’utilisent pas ControlTemplate pour définir leur apparence.

Comme nous l’avons mentionné dans la section précédente, pour éviter une expérience de navigation déroutante, nous vous recommandons de ne pas spécifier explicitement les éléments enfants d’une zone directionnelle dans l’ordre de navigation onglet de votre application. Pour plus d’informations sur le comportement de tabulation d’un élément, consultez UIElement.TabFocusNavigation et les propriétés TabIndex .

Pour les versions antérieures à Mise à jour Windows 10 Créateurs (build 10.0.15063), les paramètres de tabulation étaient limités aux objets ControlTemplate. Pour plus d’informations, consultez Control.TabNavigation.

TabFocusNavigation a une valeur de type KeyboardNavigationMode avec les valeurs possibles suivantes (notez que ces exemples ne sont pas des groupes de contrôles personnalisés et ne nécessitent pas de navigation interne avec les touches de direction) :

  • Les index tabulation locaux (par défaut) sont reconnus sur la sous-arborescence locale à l’intérieur du conteneur. Pour cet exemple, l’ordre de tabulation est B1, B2, B3, B4, B5, B6, B7, B1.

    Comportement de navigation de l’onglet « Local »

    Comportement de navigation de l’onglet « Local »

  • Une fois que le conteneur et tous les éléments enfants reçoivent le focus une seule fois. Pour cet exemple, l’ordre de tabulation est B1, B2, B7, B1 (la navigation interne avec flèche est également illustrée).

    Comportement de navigation de l’onglet « Une fois »

    Comportement de navigation de l’onglet « Une fois »

  • Cycle
    Le focus revient à l’élément focusable initial à l’intérieur d’un conteneur. Pour cet exemple, l’ordre de tabulation est B1, B2, B3, B4, B5, B6, B2...

    Comportement de navigation de l’onglet « Cycle »

    Comportement de navigation de l’onglet « Cycle »

Voici le code des exemples précédents (avec TabFocusNavigation ="Cycle »).

<Grid 
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" 
    TabFocusNavigation="Cycle">
    <Grid.RowDefinitions>
        <RowDefinition Height="40"/>
        <RowDefinition Height="300"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <TextBlock Name="KeyPressed"
               Grid.Row="0" 
               FontWeight="ExtraBold" 
               HorizontalTextAlignment="Center"
               TextWrapping="Wrap" 
               Padding="10" />
    <StackPanel Name="ContainerPrimary"
                KeyDown="Container_KeyDown" 
                Orientation="Horizontal" 
                HorizontalAlignment="Center"
                BorderBrush="Green" 
                BorderThickness="2" 
                Grid.Row="1" 
                Padding="10" 
                MaxWidth="200">
        <Button Name="B1" 
                Content="B1" 
                GettingFocus="Btn_GettingFocus" 
                Margin="5"/>
        <StackPanel Name="ContainerSecondary" 
                    KeyDown="Container_KeyDown"
                    XYFocusKeyboardNavigation="Enabled" 
                    TabFocusNavigation ="Cycle"
                    Orientation="Vertical" 
                    VerticalAlignment="Center"
                    BorderBrush="Red" 
                    BorderThickness="2"
                    Padding="5" Margin="5">
            <Button Name="B2" 
                    Content="B2" 
                    GettingFocus="Btn_GettingFocus" 
                    Margin="5"/>
            <Button Name="B3" 
                    Content="B3" 
                    GettingFocus="Btn_GettingFocus" 
                    Margin="5"/>
            <Button Name="B4" 
                    Content="B4" 
                    GettingFocus="Btn_GettingFocus" 
                    Margin="5"/>
            <Button Name="B5" 
                    Content="B5" 
                    GettingFocus="Btn_GettingFocus" 
                    Margin="5"/>
            <Button Name="B6" 
                    Content="B6" 
                    GettingFocus="Btn_GettingFocus" 
                    Margin="5"/>
        </StackPanel>
        <Button Name="B7" 
                Content="B7" 
                GettingFocus="Btn_GettingFocus" 
                Margin="5"/>
    </StackPanel>
</Grid>

TabIndex

Utilisez TabIndex pour spécifier l’ordre dans lequel les éléments reçoivent le focus lorsque l’utilisateur navigue dans les contrôles à l’aide de la touche Tab. Un contrôle avec un index tabulation inférieur reçoit le focus avant qu’un contrôle avec un index supérieur.

Lorsqu’un contrôle n’a pas de tabIndex spécifié, il reçoit une valeur d’index supérieure à la valeur d’index la plus élevée actuelle (et la priorité la plus basse) de tous les contrôles interactifs dans l’arborescence visuelle, en fonction de l’étendue.

Tous les éléments enfants d’un contrôle sont considérés comme une étendue, et si l’un de ces éléments possède également des éléments enfants, ils sont considérés comme une autre étendue. Toute ambiguïté est résolue en choisissant le premier élément de l’arborescence visuelle de l’étendue.

Pour exclure un contrôle de l’ordre de tabulation, définissez la propriété IsTabStop sur false.

Remplacez l’ordre de tabulation par défaut en définissant la propriété TabIndex .

Remarque

TabIndex fonctionne de la même façon avec UIElement.TabFocusNavigation et Control.TabNavigation.

Ici, nous montrons comment la navigation de focus peut être affectée par la propriété TabIndex sur des éléments spécifiques.

Navigation par onglet « Local » avec comportement TabIndex

Navigation par onglet « Local » avec comportement TabIndex

Dans l’exemple précédent, il existe deux étendues :

  • B1, zone directionnelle (B2 - B6) et B7
  • zone directionnelle (B2 - B6)

Lorsque B3 (dans la zone directionnelle) obtient le focus, l’étendue change et la navigation par onglet se transfère vers la zone directionnelle où le meilleur candidat pour le focus ultérieur est identifié. Dans ce cas, B2 suivi de B4, B5 et B6. L’étendue change ensuite à nouveau et le focus passe à B1.

Voici le code de cet exemple.

<Grid
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    TabFocusNavigation="Cycle">
    <Grid.RowDefinitions>
        <RowDefinition Height="40"/>
        <RowDefinition Height="300"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <TextBlock Name="KeyPressed"
               Grid.Row="0"
               FontWeight="ExtraBold"
               HorizontalTextAlignment="Center"
               TextWrapping="Wrap"
               Padding="10" />
    <StackPanel Name="ContainerPrimary"
                KeyDown="Container_KeyDown"
                Orientation="Horizontal"
                HorizontalAlignment="Center"
                BorderBrush="Green"
                BorderThickness="2"
                Grid.Row="1"
                Padding="10"
                MaxWidth="200">
        <Button Name="B1"
                Content="B1"
                TabIndex="1"
                ToolTipService.ToolTip="TabIndex = 1"
                GettingFocus="Btn_GettingFocus"
                Margin="5"/>
        <StackPanel Name="ContainerSecondary"
                    KeyDown="Container_KeyDown"
                    TabFocusNavigation ="Local"
                    Orientation="Vertical"
                    VerticalAlignment="Center"
                    BorderBrush="Red"
                    BorderThickness="2"
                    Padding="5" Margin="5">
            <Button Name="B2"
                    Content="B2"
                    GettingFocus="Btn_GettingFocus"
                    Margin="5"/>
            <Button Name="B3"
                    Content="B3"
                    TabIndex="3"
                    ToolTipService.ToolTip="TabIndex = 3"
                    GettingFocus="Btn_GettingFocus"
                    Margin="5"/>
            <Button Name="B4"
                    Content="B4"
                    GettingFocus="Btn_GettingFocus"
                    Margin="5"/>
            <Button Name="B5"
                    Content="B5"
                    GettingFocus="Btn_GettingFocus"
                    Margin="5"/>
            <Button Name="B6"
                    Content="B6"
                    GettingFocus="Btn_GettingFocus"
                    Margin="5"/>
        </StackPanel>
        <Button Name="B7"
                Content="B7"
                TabIndex="2"
                ToolTipService.ToolTip="TabIndex = 2"
                GettingFocus="Btn_GettingFocus"
                Margin="5"/>
    </StackPanel>
</Grid>

Navigation directionnelle 2D pour le clavier, le boîtier de commande et le contrôle à distance

Les types d’entrée non pointeurs tels que le clavier, le boîtier de commande, le contrôle à distance et les outils d’accessibilité tels que le Narrateur Windows, partagent un mécanisme commun sous-jacent permettant de naviguer et d’interagir avec l’interface utilisateur de votre application Windows.

Dans cette section, nous expliquons comment spécifier une stratégie de navigation préférée et affiner la navigation au sein de votre application via un ensemble de propriétés de stratégie de navigation qui prennent en charge tous les types d’entrée non pointeurs basés sur le focus.

Pour plus d’informations générales sur la création d’applications et d’expériences pour Xbox/TV, consultez Interaction clavier, Conception pour Xbox et TV, et interactions de boîtier de commande à distance et boîtier de commande à distance.

Les stratégies de navigation s’appliquent au clavier, au boîtier de commande, au contrôle à distance et à divers outils d’accessibilité.

Les propriétés de stratégie de navigation suivantes vous permettent d’influencer le contrôle qui reçoit le focus en fonction de la touche de direction, du bouton du pavé directionnel (D-pad) ou d’un appui similaire.

  • XYFocusUpNavigationStrategy
  • XYFocusDownNavigationStrategy
  • XYFocusLeftNavigationStrategy
  • XYFocusRightNavigationStrategy

Ces propriétés ont des valeurs possibles d’Auto (par défaut), navigationDirectionDistance, Projection ou RectilinearDistance .

Si la valeur est Automatique, le comportement de l’élément est basé sur les ancêtres de l’élément. Si tous les éléments sont définis sur Auto, Projection est utilisée.

Remarque

D’autres facteurs, tels que l’élément précédemment concentré ou la proximité de l’axe de la direction de navigation, peuvent influencer le résultat.

Projection

La stratégie de projection déplace le focus sur le premier élément rencontré lorsque le bord de l’élément actuellement ciblé est projeté dans la direction de la navigation.

Dans cet exemple, chaque direction de navigation de focus est définie sur Projection. Notez comment le focus passe de B1 à B4, en contournant B3. Cela est dû au fait que B3 n’est pas dans la zone de projection. Notez également comment un candidat de focus n’est pas identifié lors du déplacement à gauche de B1. Cela est dû au fait que la position de B2 par rapport à B1 élimine B3 comme candidat. Si B3 était dans la même ligne que B2, il s’agirait d’un candidat viable pour la navigation de gauche. B2 est un candidat viable en raison de sa proximité non obstruée de l’axe de la direction de navigation.

Stratégie de navigation de projection

Stratégie de navigation de projection

La stratégie NavigationDirectionDistance déplace le focus sur l’élément le plus proche de l’axe de la direction de navigation.

Le bord du rect englobant correspondant à la direction de navigation est étendu et projeté pour identifier les cibles candidates. Le premier élément rencontré est identifié comme cible. Dans le cas de plusieurs candidats, l’élément le plus proche est identifié comme cible. S’il existe toujours plusieurs candidats, l’élément le plus à gauche/le plus haut est identifié comme candidat.

Stratégie de navigation NavigationDirectionDistance

Stratégie de navigation NavigationDirectionDistance

RectilinearDistance

La stratégie RectilinearDistance déplace le focus sur l’élément le plus proche en fonction de la distance rectiligne 2D (géométrie Taxicab).

La somme de la distance primaire et de la distance secondaire à chaque candidat potentiel est utilisée pour identifier la meilleure candidature. Dans une liaison, le premier élément à gauche est sélectionné si la direction demandée est vers le haut ou vers le bas, et le premier élément en haut est sélectionné si la direction demandée est gauche ou droite.

Stratégie de navigation RectilinearDistance

Stratégie de navigation RectilinearDistance

Cette image montre comment, quand B1 a le focus et le bas est la direction demandée, B3 est le candidat de focus RectilinearDistance. Cela est basé sur les calcualations suivantes pour cet exemple :

  • Distance (B1, B3, Down) est 10 + 0 = 10
  • Distance (B1, B2, Down) est de 0 + 40 = 30
  • Distance (B1, D, Down) est 30 + 0 = 30