c# - Shift+Tab no funciona en el control TreeView
wpf navigation (2)
Si observa el manejador TreeView.OnKeyDown utilizando ILSpy / Reflector, puede ver la causa de sus problemas. El TreeView tiene un manejo especial cuando se presiona Shift + Tab. El código relevante es:
Key key = e.Key;
if (key != Key.Tab) {
// ...
}
else {
if (TreeView.IsShiftKeyDown && base.IsKeyboardFocusWithin &&
this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Previous))) {
e.Handled = true;
return;
}
}
Desafortunadamente, necesitarías usar una clase TreeView personalizada para evitar esto. Algo como esto funciona:
public class MyTreeView : TreeView {
protected override void OnKeyDown(KeyEventArgs e) {
if ((Keyboard.Modifiers & ModifierKeys.Shift) != 0 && e.Key == Key.Tab)
return;
base.OnKeyDown(e);
}
}
No puedo obtener navegación hacia atrás usando Shift + Tab para trabajar en un TreeView que contiene TextBoxs, reenviar navegación usando Tab funciona bien y saltar de TextBox a TextBox dentro de TreeView. En cualquier momento Shift + Tab se usa cuando uno de los cuadros de texto dentro de TreeView, luego el foco se mueve al control anterior fuera de TreeView, en lugar del control anterior dentro de TreeView.
Además, su única navegación Shift + Tab que no funciona correctamente, Ctrl + Shift + Tab funciona como se espera y en el orden correcto.
¿Alguna sugerencia de lo que estoy haciendo mal?
Código de ejemplo:
<Window x:Class="TestTabTreeView.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="TreeViewItem">
<Setter Property="KeyboardNavigation.TabNavigation" Value="Continue" />
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBox Text="First Line" Grid.Row="0" />
<TreeView Grid.Row="1" KeyboardNavigation.TabNavigation="Continue" IsTabStop="False">
<TreeViewItem IsExpanded="True"><TreeViewItem.Header><TextBox Text="Popular Words"/></TreeViewItem.Header>
<TreeViewItem><TreeViewItem.Header><TextBox Text="Foo"/></TreeViewItem.Header></TreeViewItem>
<TreeViewItem><TreeViewItem.Header><TextBox Text="Bar"/></TreeViewItem.Header></TreeViewItem>
<TreeViewItem><TreeViewItem.Header><TextBox Text="Hello"/></TreeViewItem.Header></TreeViewItem>
</TreeViewItem>
<TreeViewItem IsExpanded="True"><TreeViewItem.Header><TextBox Text="Unpopular Words"/></TreeViewItem.Header>
<TreeViewItem><TreeViewItem.Header><TextBox Text="Work"/></TreeViewItem.Header></TreeViewItem>
<TreeViewItem><TreeViewItem.Header><TextBox Text="Duplication"/></TreeViewItem.Header></TreeViewItem>
</TreeViewItem>
</TreeView>
<TextBox Text="Last Line" Grid.Row="2" />
</Grid>
No tiene que usar una clase personalizada heredada de TreeView:
treeView.PreviewKeyDown += this.HandleTreeView_PreviewKeyDown
Juntos con:
private void HandleTreeView_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.KeyboardDevice.Modifiers.HasFlag(ModifierKeys.Shift)
&& e.Key == Key.Tab)
{
var focusedElement = Keyboard.FocusedElement;
if (focusedElement != null)
{
focusedElement.MoveFocus(FocusNavigationDirection.Previous, 1);
}
e.Handled = true;
}
}
También funciona bien.
Con esta solución, podría, por ejemplo, crear un comportamiento personalizado y adjuntarlo a su TreeView.