How to change the focus move direction of Tab and Shift+Tab key in DataGrid.

Dec 1, 2008 at 3:40 AM
Edited Dec 1, 2008 at 3:41 AM
The default keyboard navigation of Tab key in DataGrid is move focus from one DataGridCell to another.

But I need the focus can be moved to the next DataGridRow when [Tab] key is pressed.

I tried to use KeyboardNavigation.TabNavigation attached property, but when Tab key is pressed,

the focus is moved out of DataGrid, not to the next DataGridRow.

            <Style x:Key="defaultRowStyle" TargetType="{x:Type dg:DataGridRow}">

                <Setter Property="Header" Value="{Binding Id}"/>

                <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>

            </Style>

How can I control the focus move direction?

I think one solution may work is to write code in PreviewKeyUp.

Dec 1, 2008 at 9:13 AM
As I recall, the DataGrid uses WPF's command subsystem for all its keyboard shortcuts. So while I haven't tried it, you should be able to set up a new command with an InputGesture(Key=Tab) that advances the selection to the next row.

Hope this helps.
Dec 1, 2008 at 10:17 AM
Thank you. Now I can use the event handler of PreviewKeyDown to change focus when Tab/Shift+Tab is pressed.
I don't know whether there are any side effects.
Now the code is just a trial and it does not take the Editing mode of Cell into account.


        private void DataGrid1_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Tab)
            {
                bool previous = ((e.KeyboardDevice.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift);
                // Start navigation from the current focus to allow moving focus on other focusable elements inside the cell
                UIElement startElement = Keyboard.FocusedElement as UIElement;
                ContentElement startContentElement = (startElement == null) ? Keyboard.FocusedElement as ContentElement : null;
                if ((startElement != null) || (startContentElement != null))
                {
                    e.Handled = true;

                    FocusNavigationDirection direction = previous ? FocusNavigationDirection.Up : FocusNavigationDirection.Down;
                    TraversalRequest request = new TraversalRequest(direction);
                    request.Wrapped = true; // Navigate only within datagrid

                    // Move focus to the the next or previous tab stop.
                    if (((startElement != null) && startElement.MoveFocus(request)) ||
                        ((startContentElement != null) && startContentElement.MoveFocus(request)))
                    {
                        UIElement currentElement = Keyboard.FocusedElement as UIElement;
                        DataGridRow currentRow = FindVisualParent<DataGridRow>(currentElement);
                        if (currentRow != null) currentRow.IsSelected = true;
                    }
                }
            }

        }

        public static T FindVisualParent<T>(UIElement element) where T : UIElement
        {
            UIElement parent = element;
            while (parent != null)
            {
                T correctlyTyped = parent as T;
                if (correctlyTyped != null)
                {
                    return correctlyTyped;
                }

                parent = VisualTreeHelper.GetParent(parent) as UIElement;
            }

            return null;
        }