Disable tabstop between columns in a WPF datagrid
Thank you rmoore. To get the tab stop to be disabled for columns I took your answer and modified it slightly;
<my:DataGrid Name="datagrid"
AutoGenerateColumns="False" IsReadOnly="True"
CanUserAddRows="False" CanUserDeleteRows="False"
Background="White"
KeyboardNavigation.TabNavigation="Once"
SelectionUnit="FullRow">
<my:DataGrid.Columns>
<my:DataGridTextColumn x:Name="ID" Header="ID" Width="1*" ></my:DataGridTextColumn>
<my:DataGridTextColumn x:Name="Ticker" Header="Ticker" Width="1*">
<my:DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type my:DataGridCell}">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False"></Setter>
</Style>
</my:DataGridTextColumn.CellStyle>
</my:DataGridTextColumn>
<my:DataGridTextColumn x:Name="OfficialName" Header="Name" Width="3*">
<my:DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type my:DataGridCell}">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False"></Setter>
</Style>
</my:DataGridTextColumn.CellStyle>
</my:DataGridTextColumn>
</my:DataGrid.Columns>
</my:DataGrid>
So tricks;
- SelectionUnit="FullRow" makes the GUI look like you are doing things one row at a time (like I wanted).
- By adding a CellStyle to the columns I want to disable TabStop in (but not including it in those I would like to stop in) allowed me to take control over which cells that tab-key would navigate into. - The KeyboardNavigation.TabNavigation not having an effect when defined on columns.
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.
I know this is a really old question, but I'm posting this here in case it helps someone. While the accepted answer is good, I don't believe it covers the case where there's another control on the same window, and you would like to tab into the DataGrid
from that control. Additionally, you may want the behavior as described in the original question (single tab in, single tab out, no tabbing through cells/columns). This solution aims to achieve this.
Note: This solution is assuming you want your SelectionUnit
to be FullRow
in your DataGrid
.
First, here is the Style
to apply to the DataGrid
:
<DataGrid.Resources>
<Style TargetType="DataGridRow">
<Style.Setters>
<Setter Property="Focusable" Value="True"/>
</Style.Setters>
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="IsSelected" Value="True"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="DataGridCell">
<Style.Setters>
<Setter Property="Focusable" Value="False"/>
</Style.Setters>
</Style>
</DataGrid.Resources>
This style allows focus on rows but prevents focus on individual cells, which keeps the focus consistent with the SelectionUnit
of FullRow
. The trigger set inside this style is optional - it is only needed if you want to automatically select the row when it receives focus.
In my case, I wanted the single tab in / tab out behavior, so I also set the KeyboardNavigation.TabNavigation
property on my DataGrid
= "Once."
<DataGrid SelectionUnit="FullRow" KeyboardNavigation.TabNavigation="Once">
With this approach, I can still use the up/down arrow keys to cycle through rows once the DataGrid
receives focus, but I can still tab out quickly if I want to move focus to the next control in the tab order.