Visão geral do foco
No WPF existem dois conceitos principais que dizem respeito ao foco: foco do teclado e foco lógico. O foco do teclado refere-se ao elemento que recebe a entrada do teclado e o 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 nesses conceitos é importante para criar aplicativos complexos que tenham 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 o Base Elements Overview.
A classe Keyboard está preocupada principalmente com o foco do teclado e a FocusManager está preocupada principalmente com o foco lógico, mas esta não é uma distinção absoluta. Um elemento que tem foco de teclado também terá foco lógico, mas um elemento que tem foco lógico não tem necessariamente foco de teclado. Isso é aparente quando você usa a classe Keyboard para definir o elemento que tem o foco do teclado, pois ele também define o foco lógico no elemento.
Foco do teclado
O foco do teclado refere-se ao elemento que está recebendo a entrada do teclado no momento. Pode haver apenas um elemento em toda a área de trabalho que tem foco no teclado. No WPF, o elemento que tem foco no teclado terá IsKeyboardFocused definido como true
. A propriedade estática FocusedElement na classe Keyboard obtém o elemento que atualmente está com o foco do teclado.
Para que um elemento obtenha o foco do teclado, as propriedades Focusable e IsVisible nos elementos base devem ser definidas como true
. Algumas classes, como a classe base Panel, têm Focusable definido como false
por padrão. Portanto, deve definir Focusable como true
se quiser que esse elemento seja capaz de obter o foco do teclado.
O foco do teclado pode ser obtido através da interação do utilizador com a interface, como navegar até um elemento ou clicar com o rato em certos elementos. O foco do teclado também pode ser obtido programaticamente usando o método Focus na classe Keyboard. O método Focus tenta dar ao elemento especificado o foco do teclado. O elemento retornado é o elemento que tem o foco do teclado, que pode ser um elemento diferente do solicitado se o objeto de foco antigo ou novo 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);
}
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
A propriedade IsKeyboardFocused nas classes de elemento base obtém um valor que indica se o elemento tem foco no teclado. A propriedade IsKeyboardFocusWithin nas classes de elemento base obtém um valor que indica se o elemento ou qualquer um de seus elementos filho visuais tem foco de teclado.
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 definidos como true
. O local recomendado para definir o foco inicial é no manipulador de eventos Loaded. Uma chamada de retorno Dispatcher também pode ser usada chamando Invoke ou BeginInvoke.
Foco lógico
Foco lógico refere-se ao FocusManager.FocusedElement em um escopo de foco. Um escopo de foco é um elemento que acompanha o FocusedElement no seu âmbito. Quando o foco do teclado deixa um escopo de foco, o elemento focado perderá o foco do teclado, mas manterá o foco lógico. Quando o foco do teclado regressa à área de foco, o elemento focado obterá o foco do teclado. Isso permite que o foco do teclado seja alterado entre vários escopos de foco, mas garante que o elemento focado no escopo de foco recupere o foco do teclado quando o foco retornar ao escopo de foco.
Pode haver vários elementos que têm foco lógico em um aplicativo, mas pode haver apenas um elemento que tem foco lógico em um escopo de foco específico.
Um elemento que tem foco no teclado tem foco lógico para o escopo de foco ao qual pertence.
Um elemento pode ser transformado em um escopo de foco em Extensible Application Markup Language (XAML) definindo a propriedade FocusManager anexada IsFocusScope como true
. No código, um elemento pode ser transformado em um escopo de foco chamando SetIsFocusScope.
O exemplo a seguir transforma um StackPanel em um escopo de foco definindo a propriedade IsFocusScope anexada.
<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 retorna o escopo de foco para o elemento especificado.
As classes no WPF que são escopos de foco por padrão são Window, MenuItem, ToolBare ContextMenu.
GetFocusedElement obtém o elemento focado para o escopo de foco especificado. SetFocusedElement define o elemento focalizado no escopo de foco especificado. SetFocusedElement é normalmente usado para definir o elemento focado inicial.
O exemplo a seguir define o elemento focado em um escopo de foco e obtém o elemento focado 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);
' 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)
Navegação por teclado
A classe KeyboardNavigation é responsável por implementar a navegação de foco do teclado padrão quando uma das teclas de navegação é pressionada. As teclas de navegação são: teclas TAB, SHIFT+TAB, CTRL+TAB, CTRL+SHIFT+TAB, UPARROW, DOWNARROW, LEFTARROW e RIGHTARROW.
O comportamento de navegação de um contêiner de navegação pode ser alterado definindo as propriedades KeyboardNavigation anexadas TabNavigation, ControlTabNavigatione DirectionalNavigation. Essas propriedades são do tipo KeyboardNavigationMode e os valores possíveis são Continue, Local, Contained, Cycle, Oncee None. O valor padrão é Continue, o que significa que o elemento não é um contêiner de navegação.
O exemplo a seguir cria um Menu com vários objetos MenuItem. A propriedade TabNavigation anexada está definida como Cycle em Menu. Quando o foco é alterado usando a tecla tab dentro do Menu, o foco se moverá de cada elemento e, quando o último elemento for atingido, o foco retornará ao 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);
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)
Navegação do Foco de Forma Programática
API adicionais para trabalhar com foco são MoveFocus e PredictFocus.
MoveFocus muda o foco para o próximo elemento no aplicativo. Um TraversalRequest é usado para especificar a direção. O FocusNavigationDirection passado para MoveFocus especifica as diferentes direções em que o foco pode ser movido, como First, Last, Up e Down.
O exemplo a seguir usa MoveFocus para alterar o elemento focado.
// 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 retorna o objeto que receberia foco se o foco fosse alterado. Atualmente, apenas Up, Down, Lefte Right são suportados pelo PredictFocus.
Eventos em 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 facilmente acessíveis como eventos roteados equivalentes nas classes de elemento base. Para obter mais informações sobre eventos, consulte a Visão geral de eventos roteados .
GotKeyboardFocus é ativado quando o elemento obtém o foco do teclado.
LostKeyboardFocus é aumentada quando o elemento perde o foco do teclado. Se o evento PreviewGotKeyboardFocus ou o evento PreviewLostKeyboardFocusEvent for manipulado e Handled estiver definido como true
, o foco não será alterado.
O exemplo a seguir anexa manipuladores de eventos GotKeyboardFocus e LostKeyboardFocus a 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 do 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();
}
}
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
Quando o TextBox perde o foco do teclado, a propriedade Background do TextBox é alterada de volta para o 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();
}
}
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
Os eventos relacionados com o foco lógico são GotFocus e LostFocus. Esses eventos são definidos no FocusManager como eventos anexados, mas o FocusManager não expõe envoltórios de eventos CLR. UIElement e ContentElement tornam esses eventos mais facilmente acessíveis.
Ver também
- FocusManager
- UIElement
- ContentElement
- Visão geral da entrada
- Visão geral dos elementos base
.NET Desktop feedback