wpfxamlwpfdatagridtabstop

Disable tabstop between columns in a WPF datagrid


I have a WPF Toolkit datagrid with mulitple columns. I am trying to get a behaviour where you can tab into the grid using tab, then tab out again using a single tab. E.g. I do not want to tab through all the columns or cells of the grid, just once in, and once out.

Is there a simple solution, I have tried setting the TabNavigation to Once, along with disabling TabStop (not shown in code below) and setting TabNavigation on the columns to None, but without success.

Is there something I am missing or do I need to handle the Tab-key in code?

        <my:DataGrid Name="datagrid"
                     AutoGenerateColumns="False" IsReadOnly="True"
                     CanUserAddRows="False" CanUserDeleteRows="False"
                     Background="White"
                     KeyboardNavigation.TabNavigation="Once">
            <my:DataGrid.Columns>
                <my:DataGridTextColumn x:Name="ID" Header="ID" Width="1*" ></my:DataGridTextColumn>
                <my:DataGridTextColumn x:Name="Ticker" Header="Ticker" Width="1*" KeyboardNavigation.TabNavigation="None"></my:DataGridTextColumn>
                <my:DataGridTextColumn x:Name="OfficialName" Header="Name" Width="3*" KeyboardNavigation.TabNavigation="None"></my:DataGridTextColumn>
            </my:DataGrid.Columns>
        </my:DataGrid>

Solution

  • It's interesting that setting the KeyboardNavigation directly on the DataGridTextColumn's doesn't work. An alternative that should work is to set up a DataGridCell style.

    <toolkit:DataGrid.CellStyle>
        <Style TargetType="{x:Type toolkit:DataGridCell}">
            <Setter Property="KeyboardNavigation.IsTabStop"
                    Value="False" />
            <Style.Triggers>
                <Trigger Property="IsSelected"
                         Value="True">
                    <Setter Property="KeyboardNavigation.IsTabStop"
                            Value="True" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </toolkit:DataGrid.CellStyle>
    

    Attaching this to the DataGrid will ensure that a cell is only a TabStop if it is already selected. However, if you are selecting full rows and don't have SelectionUnit="Cell" set on the DataGrid, it will still cycle through each column of the currently selected row.

    Instead, we can create multiple CellStyles as resources within the DataGrid:

    <toolkit:DataGrid.Resources>
    
        <Style  x:Key="SelectableCellStyle"
                TargetType="{x:Type toolkit:DataGridCell}">
            <Setter Property="KeyboardNavigation.IsTabStop"
                    Value="False" />
            <Style.Triggers>
                <Trigger Property="IsSelected"
                         Value="True">
                    <Setter Property="KeyboardNavigation.IsTabStop"
                            Value="True" />
                </Trigger>
            </Style.Triggers>
        </Style>
    
        <Style TargetType="{x:Type toolkit:DataGridCell}">
            <Setter Property="KeyboardNavigation.IsTabStop"
                    Value="False" />
        </Style>
    
    </toolkit:DataGrid.Resources>
    

    Now we have a style being applied to all DataGridCells by default and turning off TabStop, and a keyed style that allows selection when the Cell (or whole Row) is selected. Applying this style to only a single column will give us the same single-tab-in effect while allowing the whole row and all of it's columns to be selected.

     <my:DataGridTextColumn x:Name="ID" Header="ID" Width="1*" CellStyle={StaticResource  SelectableCellStyle}"/>
    

    This does also stop tabbing into the DataGrid if nothing is selected, which may be preferred or not depending on the situation you are using it in.