[ACCEPTED]-WPF datagrid and the tab key-key-bindings
I wanted this for my line-of-business software, and 17 the only way I have found to solve it is 16 by codebehind, using the PreviewKeyDown, GotKeyboardFocus 15 and LostKeyboardFocus events of the datagrid. I 14 have put these eventhandlers in a WPF decorator, to 13 avoid repeating it for every single DataGrid. It 12 would probably be possible to subclass the 11 DataGrid, but I haven't tried that.
The code 10 for the handlers are as follows (DataGrid 9 is x:Name="grid" for this sample code):
private IInputElement lastDataGridFocus = null;
private int selectedcolumnindex = 0;
void grid_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
if (grid.Items.Count > 0 && (e.NewFocus is DataGrid || (e.NewFocus is DataGridCell && !(e.OldFocus is DataGridCell))))
{
DataGridCell cell = null;
if (lastDataGridFocus != null)
{
FocusManager.SetFocusedElement(grid, lastDataGridFocus);
lastDataGridFocus = null;
e.Handled = true;
return;
}
if (grid.SelectedCells.Count == 0)
{
DataGridRow rowContainer = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(0);
if (rowContainer != null)
{
DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);
cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex((selectedcolumnindex < 0) ? 0 : selectedcolumnindex);
}
}
else
{
DataGridCellInfo selectedDataGridCellInfo = (grid.SelectedCells[0] as DataGridCellInfo?).Value;
DataGridRow rowContainer = (DataGridRow)grid.ItemContainerGenerator.ContainerFromItem(selectedDataGridCellInfo.Item);
if (rowContainer != null)
{
DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);
cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex((selectedcolumnindex < 0) ? 0 : selectedcolumnindex);
}
}
if (null != cell)
{
FocusManager.SetFocusedElement(grid, cell as IInputElement);
e.Handled = true;
}
}
}
void grid_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
if (!(e.NewFocus is DataGridCell))
{
if (grid.CurrentCell != null)
{
selectedcolumnindex = grid.Columns.IndexOf(grid.CurrentCell.Column);
}
}
}
void grid_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (Keyboard.Modifiers == ModifierKeys.Shift && e.Key == Key.Tab)
{
lastDataGridFocus = Keyboard.FocusedElement;
grid.MoveFocus(new TraversalRequest(FocusNavigationDirection.Previous));
e.Handled = true;
}
else if (Keyboard.Modifiers == ModifierKeys.None && e.Key == Key.Tab)
{
lastDataGridFocus = Keyboard.FocusedElement;
grid.MoveFocus(new TraversalRequest(FocusNavigationDirection.Last));
(Keyboard.FocusedElement as FrameworkElement).MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
e.Handled = true;
}
}
With 8 this code you can navigate inside the grid 7 using the cursor keys, and the tab key and 6 shift-tab key gets you out of the datagrid. If 5 you tab out of the grid and come back to 4 the grid, you also get to the same cell 3 that you left. This is what my users and 2 I want, and this is IMHO what the DataGrid 1 control should provide as default behaviour.
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.