Vue d’ensemble du focus

Dans WPF, il existe deux concepts principaux qui concernent le focus : le focus clavier et le focus logique. Le focus clavier fait référence à l’élément qui reçoit une entrée au clavier, tandis que le focus logique fait référence à l’élément d’une portée de focus qui a le focus. Ces concepts sont présentés en détail dans cette vue d’ensemble. Il est important de bien comprendre les différences entre ces concepts lors de la création d’applications complexes qui comportent plusieurs régions où le focus peut être obtenu.

Les classes principales qui participent à la gestion du focus sont la Keyboard classe, la FocusManager classe et les classes d’éléments de base, telles que UIElement et ContentElement. Pour plus d’informations sur les éléments de base, consultez Vue d’ensemble des éléments de base.

La Keyboard classe s’intéresse principalement au focus clavier et elle est principalement concernée par le FocusManager focus logique, mais ce n’est pas une distinction absolue. En effet, un élément qui a le focus clavier possède également le focus logique, tandis qu’un élément qui a le focus logique ne possède pas nécessairement le focus clavier. Cela est apparent lorsque vous utilisez la Keyboard classe pour définir l’élément qui a le focus clavier, car il définit également le focus logique sur l’élément.

Focus clavier

Le focus clavier fait référence à l’élément qui reçoit l’entrée au clavier. Un seul élément de l’ordinateur peut avoir le focus clavier. Dans WPF, l’élément qui a le focus clavier a IsKeyboardFocused la valeur true. La propriété FocusedElement statique sur la Keyboard classe obtient l’élément qui a actuellement le focus clavier.

Pour qu’un élément obtienne le focus clavier, les Focusable propriétés et les IsVisible propriétés des éléments de base doivent être définies truesur . Certaines classes, telles que la Panel classe de base, ont Focusable la valeur false par défaut . Par conséquent, vous devez définir Focusable la valeur si true vous souhaitez qu’un tel élément puisse obtenir le focus clavier.

Le focus clavier peut être obtenu par le biais d’une interaction utilisateur avec l’interface utilisateur, par exemple tabulation sur un élément ou en cliquant sur la souris sur certains éléments. Le focus clavier peut également être obtenu par programmation à l’aide de la Focus méthode sur la Keyboard classe. La Focus méthode tente d’accorder le focus clavier de l’élément spécifié. L’élément retourné correspond à l’élément qui a le focus clavier. Il peut s’agir d’un autre élément que celui demandé si l’objet de focus précédent ou nouveau bloque la demande.

L’exemple suivant utilise la méthode pour définir le Focus focus clavier sur un Button.

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

La IsKeyboardFocused propriété sur les classes d’éléments de base obtient une valeur indiquant si l’élément a le focus clavier. La IsKeyboardFocusWithin propriété sur les classes d’éléments de base obtient une valeur indiquant si l’élément ou l’un de ses éléments enfants visuels a le focus clavier.

Lorsque vous définissez le focus initial au démarrage de l’application, l’élément à recevoir doit se trouver dans l’arborescence visuelle de la fenêtre initiale chargée par l’application, et l’élément doit avoir Focusable et IsVisible défini sur true. L’emplacement recommandé pour définir le focus initial se trouve dans le gestionnaire d’événements Loaded . Un Dispatcher rappel peut également être utilisé en appelant Invoke ou BeginInvoke.

Focus logique

Le focus logique fait référence à l’étendue FocusManager.FocusedElement d’un focus. Une étendue de focus est un élément qui effectue le suivi de l’étendue FocusedElement . Quand le focus clavier quitte une portée de focus, l’élément ayant le focus perd le focus clavier, mais conserve le focus logique. Quand le focus clavier revient dans la portée de focus, l’élément ayant le focus obtient le focus clavier. Cela permet au focus clavier de changer entre des portées de focus et de s’assurer que l’élément ayant le focus dans la portée de focus retrouve le focus clavier quand le focus revient dans la portée de focus.

Plusieurs éléments d’une application peuvent avoir le focus logique, mais un seul élément peut avoir le focus logique dans une portée de focus donnée.

Un élément ayant le focus clavier a également le focus logique pour la portée de focus à laquelle il appartient.

Un élément peut être transformé en une étendue de focus dans XAML (Extensible Application Markup Language) en définissant la FocusManager propriété IsFocusScopetruejointe sur . Dans le code, un élément peut être transformé en une étendue de focus en appelant SetIsFocusScope.

L’exemple suivant transforme une StackPanel étendue de focus en définissant la IsFocusScope propriété jointe.

<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)

GetFocusScope retourne l’étendue du focus pour l’élément spécifié.

Les classes dans WPF qui sont des étendues de focus par défaut sont Window, MenuItem, ToolBaret ContextMenu.

GetFocusedElement obtient l’élément prioritaire pour l’étendue de focus spécifiée. SetFocusedElement définit l’élément prioritaire dans l’étendue de focus spécifiée. SetFocusedElement est généralement utilisé pour définir l’élément prioritaire initial.

L’exemple suivant définit l’élément ayant le focus dans une portée de focus et obtient l’élément ayant le focus d’une portée de focus.

// Sets the focused element in focusScope1
// focusScope1 is a StackPanel.
FocusManager.SetFocusedElement(focusScope1, button2);

// Gets the focused element for focusScope 1
IInputElement focusedElement = FocusManager.GetFocusedElement(focusScope1);
' Sets the focused element in focusScope1
' focusScope1 is a StackPanel.
FocusManager.SetFocusedElement(focusScope1, button2)

' Gets the focused element for focusScope 1
Dim focusedElement As IInputElement = FocusManager.GetFocusedElement(focusScope1)

Navigation au clavier

La KeyboardNavigation classe est responsable de l’implémentation de la navigation par défaut du focus clavier lorsque l’une des touches de navigation est enfoncée. Les touches de navigation sont les suivantes : TAB, MAJ+TAB, CTRL+TAB, CTRL+MAJ+TAB, FLÈCHE HAUT, FLÈCHE BAS, FLÈCHE GAUCHE et FLÈCHE DROITE.

Le comportement de navigation d’un conteneur de navigation peut être modifié en définissant les propriétés TabNavigationjointes KeyboardNavigation , ControlTabNavigationet DirectionalNavigation. Ces propriétés sont de type KeyboardNavigationMode et les valeurs possibles sont Continue, , ContainedLocal, Cycle, , Onceet None. La valeur par défaut est Continue, ce qui signifie que l’élément n’est pas un conteneur de navigation.

L’exemple suivant crée un Menu certain nombre d’objets MenuItem . La TabNavigation propriété jointe est définie Cycle sur le Menu. Lorsque le focus est modifié à l’aide de la touche tabulation dans le Menu, le focus se déplace de chaque élément et lorsque le dernier élément est atteint, le focus revient au premier élément.

<Menu KeyboardNavigation.TabNavigation="Cycle">
  <MenuItem Header="Menu Item 1" />
  <MenuItem Header="Menu Item 2" />
  <MenuItem Header="Menu Item 3" />
  <MenuItem Header="Menu Item 4" />
</Menu>
Menu navigationMenu = new Menu();
MenuItem item1 = new MenuItem();
MenuItem item2 = new MenuItem();
MenuItem item3 = new MenuItem();
MenuItem item4 = new MenuItem();

navigationMenu.Items.Add(item1);
navigationMenu.Items.Add(item2);
navigationMenu.Items.Add(item3);
navigationMenu.Items.Add(item4);

KeyboardNavigation.SetTabNavigation(navigationMenu,
    KeyboardNavigationMode.Cycle);
Dim navigationMenu As New Menu()
Dim item1 As New MenuItem()
Dim item2 As New MenuItem()
Dim item3 As New MenuItem()
Dim item4 As New MenuItem()

navigationMenu.Items.Add(item1)
navigationMenu.Items.Add(item2)
navigationMenu.Items.Add(item3)
navigationMenu.Items.Add(item4)

KeyboardNavigation.SetTabNavigation(navigationMenu, KeyboardNavigationMode.Cycle)

Une API supplémentaire pour travailler avec focus est MoveFocus et PredictFocus.

MoveFocus modifie le focus sur l’élément suivant dans l’application. A TraversalRequest est utilisé pour spécifier la direction. Le FocusNavigationDirection passage pour MoveFocus spécifier le focus des différentes directions peut être déplacé, tel que First, LastUp et Down.

L’exemple suivant utilise MoveFocus pour modifier l’élément prioritaire.

// Creating a FocusNavigationDirection object and setting it to a
// local field that contains the direction selected.
FocusNavigationDirection focusDirection = _focusMoveValue;

// MoveFocus takes a TraveralReqest as its argument.
TraversalRequest request = new TraversalRequest(focusDirection);

// Gets the element with keyboard focus.
UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;

// Change keyboard focus.
if (elementWithFocus != null)
{
    elementWithFocus.MoveFocus(request);
}
' Creating a FocusNavigationDirection object and setting it to a
' local field that contains the direction selected.
Dim focusDirection As FocusNavigationDirection = _focusMoveValue

' MoveFocus takes a TraveralReqest as its argument.
Dim request As New TraversalRequest(focusDirection)

' Gets the element with keyboard focus.
Dim elementWithFocus As UIElement = TryCast(Keyboard.FocusedElement, UIElement)

' Change keyboard focus.
If elementWithFocus IsNot Nothing Then
    elementWithFocus.MoveFocus(request)
End If

PredictFocus retourne l’objet qui recevrait le focus si le focus devait être modifié. Actuellement, seuls Up, , LeftDown, et Right sont pris en charge par PredictFocus.

Événements de focus

Les événements liés au focus clavier sont PreviewGotKeyboardFocus, GotKeyboardFocus et PreviewLostKeyboardFocus, LostKeyboardFocus. Les événements sont définis comme des événements attachés sur la Keyboard classe, mais sont plus facilement accessibles en tant qu’événements routés équivalents sur les classes d’éléments de base. Pour plus d’informations sur les événements, consultez Vue d’ensemble des événements routés.

GotKeyboardFocus est déclenché lorsque l’élément obtient le focus clavier. LostKeyboardFocus est déclenché lorsque l’élément perd le focus clavier. Si l’événement PreviewGotKeyboardFocus ou l’événement PreviewLostKeyboardFocusEvent est géré et Handled défini truesur , le focus ne change pas.

L’exemple suivant attache des gestionnaires GotKeyboardFocus d’événements à LostKeyboardFocus un TextBox.

<Border BorderBrush="Black" BorderThickness="1"
        Width="200" Height="100" Margin="5">
  <StackPanel>
    <Label HorizontalAlignment="Center" Content="Type Text In This TextBox" />
    <TextBox Width="175"
             Height="50" 
             Margin="5"
             TextWrapping="Wrap"
             HorizontalAlignment="Center"
             VerticalScrollBarVisibility="Auto"
             GotKeyboardFocus="TextBoxGotKeyboardFocus"
             LostKeyboardFocus="TextBoxLostKeyboardFocus"
             KeyDown="SourceTextKeyDown"/>
  </StackPanel>
</Border>

Lorsque le TextBox focus clavier est obtenu, la Background propriété du TextBox clavier est modifiée en LightBlue.

private void TextBoxGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    TextBox source = e.Source as TextBox;

    if (source != null)
    {
        // Change the TextBox color when it obtains focus.
        source.Background = Brushes.LightBlue;

        // Clear the TextBox.
        source.Clear();
    }
}
Private Sub TextBoxGotKeyboardFocus(ByVal sender As Object, ByVal e As KeyboardFocusChangedEventArgs)
    Dim source As TextBox = TryCast(e.Source, TextBox)

    If source IsNot Nothing Then
        ' Change the TextBox color when it obtains focus.
        source.Background = Brushes.LightBlue

        ' Clear the TextBox.
        source.Clear()
    End If
End Sub

Lorsque le TextBox focus du clavier est perdu, la Background propriété du TextBox clavier est remplacée par le blanc.

private void TextBoxLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    TextBox source = e.Source as TextBox;

    if (source != null)
    {
        // Change the TextBox color when it loses focus.
        source.Background = Brushes.White;

        // Set the  hit counter back to zero and updates the display.
        this.ResetCounter();
    }
}
Private Sub TextBoxLostKeyboardFocus(ByVal sender As Object, ByVal e As KeyboardFocusChangedEventArgs)
    Dim source As TextBox = TryCast(e.Source, TextBox)

    If source IsNot Nothing Then
        ' Change the TextBox color when it loses focus.
        source.Background = Brushes.White

        ' Set the  hit counter back to zero and updates the display.
        Me.ResetCounter()
    End If
End Sub

Les événements liés au focus logique sont GotFocus et LostFocus. Ces événements sont définis sur les FocusManager événements attachés, mais ils FocusManager n’exposent pas les wrappers d’événements CLR. UIElement et ContentElement exposer ces événements plus facilement.

Voir aussi