Compartilhar via


Visão geral sobre Foco

Em WPF há dois principais conceitos que pertencem ao foco: o foco do teclado e foco lógico. Keyboard focus refers to the element that receives keyboard input and logical focus refers to the element in a focus scope that has focus. These concepts are discussed in detail in this overview. Understanding the difference in these concepts is important for creating complex applications that have multiple regions where focus can be obtained.

The major classes that participate in focus management are the Keyboard class, the FocusManager class, and the base element classes, such as UIElement and ContentElement. For more information about the base elements, see the Visão geral sobre elementos base.

The Keyboard class is concerned primarily with keyboard focus and the FocusManager is concerned primarily with logical focus, but this is not an absolute distinction. An element that has keyboard focus will also have logical focus, but an element that has logical focus does not necessarily have keyboard focus. This is apparent when you use the Keyboard class to set the element that has keyboard focus, for it also sets logical focus on the element.

Este tópico contém as seguintes seções.

  • Keyboard Focus
  • Logical Focus
  • Keyboard Navigation
  • Navigating Focus Programmatically
  • Focus Events
  • Tópicos relacionados

Keyboard Focus

Keyboard focus refers to the element that is currently receiving keyboard input. There can be only one element on the whole desktop that has keyboard focus. In WPF, the element that has keyboard focus will have IsKeyboardFocused set to true. A propriedade estática FocusedElement sobre o Keyboard classe obtém o elemento que atualmente tem o foco do teclado.

In order for an element to obtain keyboard focus, the Focusable and the IsVisible properties on the base elements must be set to true. Some classes, such as the Panel base class, have Focusable set to false by default; therefore, you must set Focusable to true if you want such an element to be able to obtain keyboard focus.

Keyboard focus can be obtained through user interaction with the UI, such as tabbing to an element or clicking the mouse on certain elements. Keyboard focus can also be obtained programmatically by using the Focus method on the Keyboard class. O Focus método tenta dar o foco de teclado do elemento especificado. The returned element is the element that has keyboard focus, which might be a different element than requested if either the old or new focus object block the request.

The following example uses the Focus method to set keyboard focus on a Button.

        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
private void OnLoaded(object sender, RoutedEventArgs e)
{
    // Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton);
}

The IsKeyboardFocused property on the base element classes gets a value indicating whether the element has keyboard focus. The IsKeyboardFocusWithin property on the base element classes gets a value indicating whether the element or any one of its visual child elements has keyboard focus.

Ao definir o foco inicial na inicialização do aplicativo, o elemento para receber o foco deve estar na árvore visual da janela inicial carregada pelo aplicativo e o elemento deve ter Focusable e IsVisible definido como true. The recommended place to set initial focus is in the Loaded event handler. A Dispatcher callback can also be used by calling Invoke or BeginInvoke.

Logical Focus

Logical focus refers to the FocusManager.FocusedElement in a focus scope. A focus scope is an element that keeps track of the FocusedElement within its scope. When keyboard focus leaves a focus scope, the focused element will lose keyboard focus but will retain logical focus. When keyboard focus returns to the focus scope, the focused element will obtain keyboard focus. This allows for keyboard focus to be changed between multiple focus scopes but ensures that the focused element in the focus scope regains keyboard focus when focus returns to the focus scope.

There can be multiple elements that have logical focus in an application, but there may only be one element that has logical focus in a particular focus scope.

An element that has keyboard focus has logical focus for the focus scope it belongs to.

Um elemento pode ser transformado em um escopo de foco em Extensible Application Markup Language (XAML) , definindo a FocusManager anexado a propriedade IsFocusScope para true. In code, an element can be turned into a focus scope by calling SetIsFocusScope.

The following example makes a StackPanel into a focus scope by setting the IsFocusScope attached property.

<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>
            Dim focuseScope2 As New StackPanel()
            FocusManager.SetIsFocusScope(focuseScope2, True)
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);

GetFocusScope returns the focus scope for the specified element.

Classes in WPF which are focus scopes by default are Window, MenuItem, ToolBar, and ContextMenu.

GetFocusedElementObtém o elemento de foco para o escopo do foco específico. SetFocusedElementDefine o elemento centrado no escopo especificado de foco. SetFocusedElementé normalmente usado para definir o elemento de foco inicial.

The following example sets the focused element on a focus scope and gets the focused element of a focus scope.

            ' 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)
// 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);

Keyboard Navigation

The KeyboardNavigation class is responsible for implementing default keyboard focus navigation when one of the navigation keys is pressed. As teclas de navegação são: Teclas TAB, SHIFT + TAB, CTRL + TAB, CTRL + SHIFT + TAB, UPARROW, DOWNARROW, seta para a esquerda e RIGHTARROW.

The navigation behavior of a navigation container can be changed by setting the attached KeyboardNavigation properties TabNavigation, ControlTabNavigation, and DirectionalNavigation. These properties are of type KeyboardNavigationMode and the possible values are Continue, Local, Contained, Cycle, Once, and None. The default value is Continue, which means the element is not a navigation container.

The following example creates a Menu with a number of MenuItem objects. The TabNavigation attached property is set to Cycle on the Menu. Quando o foco é alterado usando a tecla tab dentro do Menu, o foco será movido de cada elemento e quando é atingido o último elemento foco irá retornar para o primeiro elemento.

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

Additional API to work with focus are MoveFocus and PredictFocus.

MoveFocus changes focus to the next element in the application. A TraversalRequest is used to specify the direction. The FocusNavigationDirection passed to MoveFocus specifies the different directions focus can be moved, such as First, Last, Up and Down.

The following example uses MoveFocus to change the focused element.

            ' 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
// 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);
}

PredictFocus returns the object which would receive focus if focus were to be changed. Currently, only Up, Down, Left, and Right are supported by PredictFocus.

Focus Events

The events related to keyboard focus are PreviewGotKeyboardFocus, GotKeyboardFocus and PreviewLostKeyboardFocus, LostKeyboardFocus. The events are defined as attached events on the Keyboard class, but are more readily accessible as equivalent routed events on the base element classes. For more information about events, see the Visão geral sobre eventos roteados.

GotKeyboardFocusé disparado quando o elemento obtém o foco do teclado. LostKeyboardFocusé disparado quando o elemento perde o foco do teclado. If the PreviewGotKeyboardFocus event or the PreviewLostKeyboardFocusEvent event is handled and Handled is set to true, then focus will not change.

The following example attaches GotKeyboardFocus and LostKeyboardFocus event handlers to a 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>

When the TextBox obtains keyboard focus, the Background property of the TextBox is changed to LightBlue.

        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
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();
    }
}

When the TextBox loses keyboard focus, the Background property of the TextBox is changed back to white.

        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
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();
    }
}

The events related to logical focus are GotFocus and LostFocus. Esses eventos são definidos na FocusManager como eventos anexados, mas o FocusManager não expõe eventos CLR wrappers. UIElemente ContentElement expõe esses eventos de forma mais conveniente.

Consulte também

Referência

FocusManager

UIElement

ContentElement

Conceitos

Input Overview

Visão geral sobre elementos base