Search code examples
c#wpfdatagridtabcontrol

WPF TabControl cannot switch tabs when hosting DataGrid


In the default TabControl you can switch tabs using Ctrl+Tab, however if one of the tabs contain DataGrid it all breaks. For example, if I had a simple TabControl containing nothing but TextBoxes:

<TabControl>
    <TabItem Header="Tab1">
        <TextBox/>
    </TabItem>
    <TabItem Header="Tab2">
        <TextBox/>
    </TabItem>
    <TabItem Header="Tab3">
        <TextBox/>
    </TabItem>
</TabControl>

And repeatedly pressed Ctrl+Tab, current Tab would cycle:

Tab1 > Tab2 > Tab3 > Tab1 > ...etc

but if I were to put virtually any DataGrid in one of the middle Tabs, for example:

...    
<TabItem Header="Tab2"> <!--replacing 2nd tab content-->
    <TabItem.Resources>
        <x:Array x:Key="Items" Type="{x:Type Run}">
            <Run Text="Foo"/>
            <Run Text="Bar"/>
            <Run Text="Baz"/>
        </x:Array>
    </TabItem.Resources>
    <DataGrid ItemsSource="{StaticResource Items}"/>
</TabItem>

the Ctrl+Tab would get stuck not being able to ever get past said Tab:

Tab1 > Tab2 > Tab1 > Tab2 > ...etc

How can I fix the issue?


I have tried IsTabStop="False" on the DataGrid and several combinations of KeyBoardNavigation properties, all of those had either no effect or were contraproductive.


Edit(2): the issue seems to appear mainly when the DataGrid is the first focusable child of TabItem, for example content:

<StackPanel>
    <TextBox/>
    <DataGrid ItemsSource="{StaticResource Items}"/>
</StackPanel>

almost works, until user selects the DataGrid. If the grid is selected next Ctrl+Tab goes back to first Tab rather than to the next one.


Solution

  • Looks like it's a focus problem, when the Datagrid gets the focus it's lost from the TabControl, so set that focus programmatically whenever the ctrl/tab is pressed where the DataGrid is:

     <TabControl  x:Name="TabCtrl">
            <TabItem Header="Tab1" x:Name="Tab1" >
                <TextBox/>
            </TabItem>
            <TabItem Header="Tab3" x:Name="Tab2"  PreviewKeyDown="UIElement_OnPreviewKeyDown">
                <TabItem.Resources>
                    <x:Array x:Key="Items" Type="{x:Type Run}">
                        <Run Text="Foo"/>
                        <Run Text="Bar"/>
                        <Run Text="Baz"/>
                    </x:Array>
                </TabItem.Resources>
                <DataGrid ItemsSource="{StaticResource Items}" />
            </TabItem>
            <TabItem Header="Tab2"  x:Name="Tab3">
                <TextBox/>
            </TabItem>
        </TabControl>
    

    The handler:

     private void UIElement_OnPreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Tab &&
                (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control && sender is TabItem)
            {
                TabCtrl.Focus();
            }
        }