Datagrid Keyboard Navigation

Jan 26, 2009 at 1:36 PM
Hi All,

How do I control the keyboard navigation in the DataGrid control? I currently have 7 columns. First 3 read only, next 2 editable, and last 2 read only again.
Currently when a user tabs, focus goes to the next cell in the row whether it is read only or not. If on the last editable cell, I want the focus to jump to the first editable cell in the next row.

I would also like to achieve this behaviour with the Enter key, but currently Enter goes one row down. I would like Enter to behave the same as Tab.

Any ideas?

Jan 26, 2009 at 7:05 PM
Create a style for DataGridCell as

            <Style TargetType="{x:Type dg:DataGridCell}" x:Key="MyCellStyle">
                <Setter Property="IsTabStop" Value="False"></Setter>

and use it as 

    <dg:DataGridTextColumn CellStyle="{StaticResource MyCellStyle}" ... />

This strategy may not work with TemplateColumns where inner controls may have tab stops for themselves in which case the template definition must have IsTabStop set to false for all such inner controls.

If this solution seems lazy then the other way of doing it is to handle key down event on DataGrid for Tab Key and implement your own behavior (this could get pretty complicated).
Jan 26, 2009 at 8:03 PM
Thanks so much VamseeP. This worked 100% and also works 100% WITH TempalteColumns.

Brilliant solution. Thanks again!!
Feb 11, 2009 at 5:52 PM
This solution does not work with me: When I press the enter key, I want the next cell to enter the edit mode and not the cell below it

 I would like Enter to behave the same as Tab.
Feb 11, 2009 at 6:38 PM
Hi AAKLebanon,

The default behavior of enter key on DataGrid is to commit the cell (if it is edting) and move to the same cell of next row. This is similar to what we have in excel and winforms datagrid.

However if one needs custom behavior, one can always get it by hooking PreviewKeyDown event handler on DataGrid and implement the needed custom behavior. In this case you can take the source code from DataGrid.OnKeyDown, DataGrid.OnTabKeyDown, DataGrid.OnArrowKeyDown and DataGrid.OnEnterKeyDown methods as reference to implement your behavior. (Note that these methods use some private stuff but you should be able to get them through public API too)
Feb 12, 2009 at 4:13 AM
Thinks for the quick reply.

I love the idea of  "zero code behind", So this lead me to inherit from the data grid and override OnKeyDown, so in case of Key.Enter I can call OnTabKeyDown instead...

however the problem is that OnTabKeyDown is private. if it is protected I think that I can solve my problem in my way...

what you think about my solution ? and there is a plan to make OnTabKeyDown, OnEnterKeyDown or OnArrowKeyDown protected (or overridables) ?
Apr 23, 2009 at 5:07 PM
Is there also a way to skip the button?  See my example below:

        <Style TargetType="{x:Type dg:DataGridCell}" x:Key="MyCellStyle">
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="BorderBrush" Value="Transparent" />
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="IsTabStop" Value="False"></Setter>

                <dg:DataGridTextColumn CellStyle="{StaticResource MyCellStyle}" Header="" Binding="{Binding Path=TimeID}" Visibility="Hidden"    />
                <dg:DataGridTextColumn CellStyle="{StaticResource MyCellStyle}" Header="Route Priority" Binding="{Binding Path=RoutePriority}" MinWidth="100" />
                <dg:DataGridTextColumn CellStyle="{StaticResource MyCellStyle}" Header="Job Address" Binding="{Binding Path=JobAddress}" MinWidth="100" />
                <dg:DataGridTextColumn CellStyle="{StaticResource MyCellStyle}" Header="Permit #"  Binding="{Binding Path=PermitNumber}" MinWidth="100" />
                <dg:DataGridTextColumn CellStyle="{StaticResource MyCellStyle}" Header="Inspection Type"  Binding="{Binding Path=TimeOptionEntry}" MinWidth="100" />
                <dg:DataGridTextColumn CellStyle="{StaticResource MyCellStyle}" Header="Start Time"  Binding="{Binding Path=StartTime}" MinWidth="100" />
                <dg:DataGridTextColumn CellStyle="{StaticResource MyCellStyle}" Header="End Time"  Binding="{Binding Path=EndTime}" MinWidth="100" />
                <dg:DataGridTemplateColumn  Header="" Visibility="Visible" MinWidth="50" MaxWidth="50" x:Name="SelectedGridItem">
                            <Button  Content="Delete" KeyboardNavigation.IsTabStop="False" Foreground="Black" FontSize="12" VerticalAlignment="Center" MaxWidth="50"
                                     Click="VoidButton_Click" Tag="jobid" Uid="{Binding Path=TimeID}"  Visibility="Visible" />