Partilhar via


Visão geral sobre Foco

In WPF Há dois principais conceitos que pertencem ao foco: foco do teclado e o foco lógico. O foco do teclado refere-se ao elemento que recebe entrada de teclado e foco lógico refere-se ao elemento em um escopo de foco que tem foco. Esses conceitos são discutidos em detalhes nesta visão geral. Entender a diferença entre esses conceitos é importante para a criação de aplicativos complexos que têm várias regiões onde o foco pode ser obtido.

As classes principais que participam do gerenciamento de foco são a classe Keyboard, a classe FocusManager e as classes de elemento base, como UIElement e ContentElement. Para obter mais informações sobre os elementos base, consulte Visão geral sobre elementos base.

A classe Keyboard trata principalmente o foco do teclado e a FocusManager está relacionada principalmente ao foco lógico, mas isso é não uma diferença absoluta. Um elemento que tenha o foco do teclado também terá foco lógico, mas um elemento que tenha foco lógico não necessariamente tem o foco do teclado. Isso é aparente quando você usa a classe Keyboard para definir o elemento que tem o foco do teclado, já que ele também determina o foco lógico no elemento.

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

  • Keyboard Focus
  • Logical Focus
  • Navegação do teclado
  • Foco de Navegação por Meio de Programação
  • Eventos de Foco
  • Tópicos relacionados

Keyboard Focus

O foco do teclado refere-se ao elemento que está recebendo entrada do teclado no momento. 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. O propriedade estática FocusedElement na classe Keyboard obtém o elemento que tem o foco do teclado no momento.

Para que um elemento obtenha o foco do teclado, as propriedades Focusable e IsVisible nos elementos base devem ser definidas como true. Algumas classes, tal como a classe base Panel, têm Focusable definida como false por padrão; portanto, você deve definir Focusable como true se você deseja permitir que tal elemento obtenha o foco do teclado.

O foco do teclado pode ser obtido pela interação com a UI, como tabulações para um elemento ou clique do mouse sobre determinados elementos. O foco do teclado também pode ser obtido por meio de programação usando o método Focus na classe Keyboard. O método Focus tenta dar o foco do teclado ao elemento especificado. O elemento retornado é o elemento que tem o foco do teclado, que pode ser um elemento diferente do solicitado se o velho ou o novo objeto de foco bloquear a solicitação.

O exemplo a seguir usa o método Focus para definir o foco do teclado em um Button.

private void OnLoaded(object sender, RoutedEventArgs e)
{
    // Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton);
}

A propriedade IsKeyboardFocused nas classes de elemento base obtém um valor indicando se o elemento tem ou não o foco do teclado. A propriedade IsKeyboardFocusWithin nas classes de elemento base obtém um valor indicando se o elemento ou qualquer um de seus elementos filhos visuais tem o foco do teclado.

Ao definir-se o foco inicial na inicialização do aplicativo, o elemento a receber o foco deve estar conectado a um PresentationSource e o elemento deve ter Focusable e IsVisible definidas como true. O local recomendado para definir o foco inicial em um aplicativo é no manipulador de eventos Loaded. Uma callback Dispatcher também pode ser usada chamando Invoke ou BeginInvoke.

Logical Focus

Logical focus refers to the FocusManager.FocusedElement in a focus scope. Um escopo de foco é um elemento que mantém registro dos FocusedElement dentro de seu escopo. Quando o foco de teclado deixa um escopo de foco, o elemento focalizado perderá o foco do teclado mas manterá foco lógico. Quando o foco de teclado retorna para o escopo de foco, o elemento focalizado obterá o foco do teclado. Isso permite que o foco do teclado seja alterado entre vários escopos de foco mas assegura que o elemento focalizado dentro do escopo de foco mantenha o elemento focalizado quando o foco retorna.

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.

Um elemento que tem o foco do teclado tem foco lógico para o escopo de foco ao qual ele pertence.

Um elemento pode ser ativado para um escopo de foco no Extensible Application Markup Language (XAML) definindo a propriedade anexada IsFocusScope de FocusManager para true. No código, um elemento pode ser inserido em um escopo de foco chamando 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>
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);

GetFocusScope retorna o escopo de foco para o elemento especificado.

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

GetFocusedElement obtém o elemento de foco para o escopo do foco especificado. SetFocusedElement Define o elemento focalizado no escopo especificado foco. SetFocusedElement costuma ser usado para conjunto o elemento de foco inicial.

O exemplo a seguir define o elemento focalizado em um escopo de foco e obtém o elemento focalizado de um escopo de foco.

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

A classe KeyboardNavigation é responsável pela implementação da navegação padrão de foco de teclado quando uma das teclas de navegação é pressionada. As teclas de navegação são: guia, deslocar + guia, CTRL+guia, CTRL + deslocar + guia, UPARROW, DOWNARROW, LEFTARROW e RIGHTARROW chaves.

O comportamento de navegação de um recipiente de navegação pode ser alterado definindo as propriedades anexadas KeyboardNavigation TabNavigation, ControlTabNavigation e DirectionalNavigation. Essas propriedades são do tipo KeyboardNavigationMode e os valores possíveis são Continue, Local, Contained, Cycle, Once e None. O valor padrão é Continue, o que significa que o elemento não é um recipiente de navegação.

O exemplo a seguir cria um Menu com um número de objetos MenuItem. A propriedade anexada TabNavigation é definida como Cycle no Menu. Quando o foco é alterado usando a tecla TAB dentro de Menu, o foco moverá de cada elemento e quando é atingido o último elemento o foco 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>
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);

Foco de Navegação por Meio de Programação

API adicionais para trabalhar com foco são MoveFocus e PredictFocus.

MoveFocus altera o foco para o próximo elemento no aplicativo. Um TraversalRequest é usado para especificar a direção. A FocusNavigationDirection passada para MoveFocus especifica as diferentes direções para as quais o foco pode ser movido, como First, Last, Up e Down.

O exemplo a seguir usa MoveFocus para alterar o elemento focalizado atualmente. Para o código-fonte completo para este exemplo, consulte Manipular o foco por programação exemplo.

// 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 retorna o objeto que deve receber o foco se o foco fosse alterado. Atualmente, somente Up, Down, Left e Right são suportados por PredictFocus.

Eventos de Foco

Os eventos relacionados ao foco do teclado são PreviewGotKeyboardFocus, GotKeyboardFocus e PreviewLostKeyboardFocus, LostKeyboardFocus. Os eventos são definidos como eventos anexados na classe Keyboard, mas são mais prontamente acessíveis como eventos roteados equivalentes nas classes de elemento base. Para obter mais informações sobre eventos, consulte Visão geral sobre eventos roteados.

GotKeyboardFocus é gerado quando o elemento obtém o foco do teclado. LostKeyboardFocus é disparado quando o elemento perde o foco do teclado. Se o evento PreviewGotKeyboardFocus ou o evento PreviewLostKeyboardFocusEvent é tratado e Handled é definida como true, então o foco não será alterado.

O exemplo a seguir anexa manipuladores de eventos GotKeyboardFocus e LostKeyboardFocus para um 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>

Quando o TextBox obtém o foco do teclado, a propriedade Background de TextBox é alterada para 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();
    }
}

Quando o TextBox perde o foco do teclado, a propriedade Background de TextBox é alterada de volta para branco.

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

Os eventos relacionados ao foco do teclado são GotFocus e LostFocus. Esses eventos são definidos no FocusManager sistema autônomo eventos anexados, mas o FocusManager não expõe wrappers de evento do CLR. UIElement e ContentElement expõe esses eventos de forma mais conveniente.

Consulte também

Conceitos

Input Overview

Visão geral sobre elementos base

Referência

FocusManager

UIElement

ContentElement