Vue d'ensemble du focus

Dans WPF, il existe deux concepts principaux associés au 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 le FocusManager s’intéresse principalement au focus logique, mais il ne s’agit pas d’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 évident lorsque vous utilisez la Keyboard classe pour définir l’élément qui a le focus clavier, pour cela 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 aura la IsKeyboardFocused valeur true . La propriété statique FocusedElement de la Keyboard classe obtient l’élément qui a actuellement le focus clavier.

Pour qu’un élément obtienne le focus clavier, les Focusable IsVisible Propriétés et sur les éléments de base doivent avoir la valeur true . Certaines classes, telles que la Panel classe de base, ont la Focusable valeur false par défaut ; par conséquent, vous devez définir Focusable sur true si vous souhaitez que ce type d’élément soit en mesure d’obtenir le focus clavier.

Le focus clavier peut être obtenu par interaction de l’utilisateur avec l’UI (tabulation vers un élément ou clic de souris sur certains éléments, par exemple). 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’attribuer le focus clavier à 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 Focus méthode pour définir le 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.

Lors du paramétrage du focus initial au démarrage de l’application, l’élément devant recevoir le focus doit se trouver dans l’arborescence d’éléments visuels de la fenêtre initiale chargée par l’application, et l’élément doit avoir et avoir la Focusable IsVisible valeur true . L’emplacement recommandé pour définir le focus initial se trouve dans le Loaded Gestionnaire d’événements. Un Dispatcher rappel peut également être utilisé en appelant Invoke ou BeginInvoke .

Focus logique

Le focus logique fait référence à FocusManager.FocusedElement dans une portée de focus. Une portée de focus est un élément qui effectue le suivi du FocusedElement dans sa portée. 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 converti en portée de focus dans langage XAML (eXtensible Application Markup Language) en affectant FocusManager à la propriété jointe la valeur IsFocusScope true . Dans le code, un élément peut être converti en portée de focus en appelant SetIsFocusScope .

L’exemple suivant rend un StackPanel en portée 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 la portée de focus pour l’élément spécifié.

Les classes dans WPF lesquelles sont des portées de focus par défaut sont Window ,, MenuItem ToolBar et ContextMenu .

GetFocusedElement Obtient l’élément ayant le focus pour la portée de focus spécifiée. SetFocusedElement définit l’élément ayant le focus dans la portée de focus spécifiée. SetFocusedElement est généralement utilisé pour définir l’élément ayant le focus 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 chargée d’implémenter 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 jointes KeyboardNavigation TabNavigation , ControlTabNavigation et DirectionalNavigation . Ces propriétés sont de type KeyboardNavigationMode et les valeurs possibles sont Continue , Local ,,, Contained Cycle Once et 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 avec un certain nombre d' MenuItem objets. La TabNavigation propriété jointe a la valeur Cycle sur Menu . Lorsque le focus est modifié à l’aide de la touche TAB dans le Menu , le focus se déplace à partir de chaque élément et, lorsque le dernier élément est atteint, le focus retourne 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)

L’API supplémentaire pour travailler avec le focus est MoveFocus et PredictFocus .

MoveFocus modifie le focus sur l’élément suivant dans l’application. Un TraversalRequest est utilisé pour spécifier la direction. Le FocusNavigationDirection passé à MoveFocus spécifie le focus des directions différentes peut être déplacé, par exemple First , Last Up et Down .

L’exemple suivant utilise MoveFocus pour modifier l’élément ayant le focus.

// 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 Down Left 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 en tant qu’é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' PreviewGotKeyboardFocus événement ou l' PreviewLostKeyboardFocusEvent événement est géré et Handled a la valeur true , le focus ne change pas.

L’exemple suivant attache GotKeyboardFocus des LostKeyboardFocus gestionnaires d’événements et à 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 TextBox obtient le focus clavier, la Background propriété du TextBox est remplacée par 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 perd le focus clavier, la Background propriété du TextBox est rétablie en 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 As attachés, mais le FocusManager n’expose pas les wrappers d’événements CLR. UIElement et ContentElement exposent ces événements plus facilement.

Voir aussi