En WPF, hay dos conceptos principales relacionados con el foco: el foco de teclado y el foco lógico. El foco de teclado hace referencia al elemento que recibe la entrada del teclado, y el foco lógico hace referencia al elemento que tiene el foco en un ámbito de foco. Estos conceptos se describen con detalle en esta información general. Entender la diferencia entre estos conceptos es importante para crear aplicaciones complejas que tengan varias regiones donde se pueda obtener el foco.
La clase Keyboard se ocupa principalmente del foco de teclado y la clase FocusManager, del foco lógico, aunque esta no es una distinción absoluta. Un elemento que tiene el foco de teclado también tendrá el foco lógico, pero un elemento que tiene el foco lógico no tendrá necesariamente el foco de teclado. Esto resulta evidente cuando se utiliza la clase Keyboard para establecer el elemento que tiene el foco de teclado, ya que también establece el foco lógico en el elemento.
Foco de teclado
El foco de teclado hace referencia al elemento que recibe actualmente la entrada del teclado. Puede haber un único elemento en todo el escritorio que tenga el foco de teclado. En WPF, el elemento que tiene el foco de teclado tendrá IsKeyboardFocused establecido en true. La propiedad estática FocusedElement de la clase Keyboard obtiene el elemento que actualmente tiene el foco de teclado.
Para que un elemento obtenga el foco de teclado, las propiedades Focusable y IsVisible de los elementos base deben estar establecidas en true. Algunas clases, como la clase base Panel, tienen Focusable establecido por defecto en false; por lo tanto, debe establecer Focusable en true si quiere que dicho elemento pueda obtener el foco de teclado.
El foco de teclado puede obtenerse a través de la interacción del usuario con la UI, como desplazarse mediante la tecla TAB hasta un elemento o hacer clic con el mouse en determinados elementos. El foco de teclado también se puede obtener mediante programación utilizando el método Focus de la clase Keyboard. El método Focus intenta dar al elemento especificado el foco de teclado. El elemento devuelto es el elemento que tiene el foco de teclado, que puede ser un elemento diferente al solicitado si el objeto que tenía el foco antes o el que tiene el foco ahora bloquean la solicitud.
El siguiente ejemplo utiliza el método Focus para fijar el foco de teclado en un Button.
C#
privatevoidOnLoaded(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 propiedad IsKeyboardFocused en las clases de elementos base obtiene un valor que indica si el elemento tiene el foco de teclado. La propiedad IsKeyboardFocusWithin en las clases de elementos base obtiene un valor que indica si el elemento o alguno de sus elementos visuales secundarios tiene el foco de teclado.
Al establecer el foco inicial al iniciarse una aplicación, el elemento que va a recibir el foco debe encontrarse en el árbol visual de la ventana inicial cargada por la aplicación, y el elemento debe tener Focusable y IsVisible establecidas en true. El lugar recomendado para establecer el foco inicial es en el controlador de eventos Loaded. Una devolución de llamada Dispatcher también puede utilizarse llamando a Invoke o BeginInvoke.
Foco lógico
El foco lógico se refiere al FocusManager.FocusedElement en un ámbito de foco. Un ámbito de foco es un elemento que lleva la cuenta de FocusedElement dentro de su ámbito. Cuando el foco de teclado sale de un ámbito de foco, el elemento enfocado pierde el foco de teclado, pero conserva el foco lógico. Cuando el foco de teclado vuelve al ámbito de foco, el elemento enfocado recibe el foco de teclado. Esto permite cambiar el foco de teclado entre varios ámbitos de foco, pero garantiza que el elemento enfocado dentro del ámbito de foco vuelva a obtener el foco de teclado cuando el foco vuelva al ámbito de foco.
Puede haber varios elementos que tengan el foco lógico en una aplicación, pero solo puede haber uno con el foco lógico en un ámbito de foco concreto.
Un elemento que tiene el foco de teclado tiene el foco lógico para el ámbito de foco al que pertenece.
Un elemento puede convertirse en un ámbito de foco en el Lenguaje de marcado de aplicaciones extensibles (XAML) estableciendo la propiedad FocusManager adjunta IsFocusScope en true. En el código, un elemento puede convertirse en un ámbito de enfoque llamando a SetIsFocusScope.
El siguiente ejemplo convierte un StackPanel en un ámbito de enfoque estableciendo la propiedad adjunta IsFocusScope.
GetFocusedElement obtiene el elemento enfocado para el ámbito de foco especificado. SetFocusedElement establece el elemento enfocado en el ámbito de foco especificado. SetFocusedElement se utiliza normalmente para establecer el elemento enfocado inicial.
En el ejemplo siguiente se establece el elemento con foco en un ámbito de foco y se obtiene el elemento con foco de un ámbito de foco.
C#
// 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)
Navegación mediante teclado
La clase KeyboardNavigation es responsable de implementar la navegación del foco de teclado predeterminada cuando se presiona una de las teclas de navegación. Las teclas de navegación son: TAB, MAYÚS+TAB, CTRL+TAB, CTRL+MAYÚS+TAB, flecha arriba, flecha abajo, flecha izquierda y flecha derecha.
El siguiente ejemplo crea un Menu con un número de objetos MenuItem. La propiedad adjunta TabNavigation se establece en Cycle en Menu. Cuando se cambie el foco mediante la tecla TAB dentro de Menu, el foco se desplazará por cada elemento y, cuando se llegue al último elemento, el foco volverá al primer elemento.
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)
El siguiente ejemplo utiliza MoveFocus para cambiar el elemento enfocado.
C#
// 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
<BorderBorderBrush="Black"BorderThickness="1"Width="200"Height="100"Margin="5"><StackPanel><LabelHorizontalAlignment="Center"Content="Type Text In This TextBox" /><TextBoxWidth="175"Height="50"Margin="5"TextWrapping="Wrap"HorizontalAlignment="Center"VerticalScrollBarVisibility="Auto"GotKeyboardFocus="TextBoxGotKeyboardFocus"LostKeyboardFocus="TextBoxLostKeyboardFocus"KeyDown="SourceTextKeyDown"/></StackPanel></Border>
privatevoidTextBoxGotKeyboardFocus(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
Cuando TextBox pierde el foco de teclado, la propiedad Background de TextBox vuelve a ser blanca.
C#
privatevoidTextBoxLostKeyboardFocus(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
Los eventos relacionados con el foco lógico son GotFocus y LostFocus. Estos eventos se definen en FocusManager como eventos adjuntos, pero FocusManager no expone contenedores de eventos CLR. UIElement y ContentElement exponen estos eventos de manera más conveniente.
El origen de este contenido se puede encontrar en GitHub, donde también puede crear y revisar problemas y solicitudes de incorporación de cambios. Para más información, consulte nuestra guía para colaboradores.
Comentarios de .NET Desktop feedback
.NET Desktop feedback es un proyecto de código abierto. Seleccione un vínculo para proporcionar comentarios:
Únase a la serie de reuniones para crear soluciones de inteligencia artificial escalables basadas en casos de uso reales con compañeros desarrolladores y expertos.
Learn how to develop keyboard-accessible products with our comprehensive module. This course covers essential guidelines, design considerations, implementation strategies, and testing methods to ensure your products are accessible to all users, including those with disabilities.
Conozca las entradas en Windows Presentation Foundation (WPF), así como la arquitectura y las clases que las controlan, y obtenga una visión completa de ellas.