Search code examples
wpfnavigationtabstop

WPF: How to disable tab navigation without also disabling arrow key navigation?


I have set IsTabStop to false on all controls in my window, so that when I press the Tab key, the focus doesn't move (I need the Tab key for something else). But doing this breaks arrow key navigation - I click on an item in a ListView and then pressing up/down doesn't change the selected item anymore.

Is there a way to disable tab navigation, but without touching arrow key navigation? They seem to be related.

I tried setting IsTabStop to true and TabNavigation to false, but it doesn't work either.

<ListView ItemContainerStyle="{StaticResource ItemCommon}" IsTabStop="False">
    <ListView.Resources>
        <Style x:Key="ItemCommon">
            <Setter Property="IsTabStop" Value="False"/>
            <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
            <Setter Property="KeyboardNavigation.DirectionalNavigation" Value="Cycle"/>
        </Style>
    </ListView.Resources>
</ListView>

Solution

  • On your window (or some ancestor of the controls you don't want tab to work on) swallow the tab key.

    You can swallow it by attaching to the PreviewKeyDown event and set e.Handled = true when the key is a tab.

    Pure Code Behind:

     public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                this.PreviewKeyDown += MainWindowPreviewKeyDown;
            }
    
            static void MainWindowPreviewKeyDown(object sender, KeyEventArgs e)
            {
                if(e.Key == Key.Tab)
                {
                    e.Handled = true;
                }
            }
        }
    

    You can also set a Keyboard handler as such:

    <Window x:Class="TabSwallowTest.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"
            Keyboard.PreviewKeyDown="Window_PreviewKeyDown" >
    
        <StackPanel>
            <TextBox Width="200" Margin="10"></TextBox>
            <TextBox Width="200" Margin="10"></TextBox>
        </StackPanel>
    </Window>
    

    but you'll need a corresponding event handler:

       private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
    
        {
            if (e.Key == Key.Tab)
            {
                e.Handled = true;
            }
        }