How to navigate current cell within selected region in WPF Datagrid?
In WPF DataGrid Excel, the current cell is navigated towards right for Tab key and down for Enter key within the selected region. You can also achieve the same requirement in SfDataGrid by deriving a new class from GridCellSelectionController and overriding the necessary virtual methods in SfDataGrid. You can refer to this link for more information about GridCellSelectionController and its available virtual method.
By using the Extended selection mode in SfDataGrid, you can achieve the selection format like in Excel as displayed in the following screenshot.
Figure 1: Default position of the current cell with in selected region
You can change the behavior of Cell selection by overriding GridCellSelectionController class.
Assign the instance of GridCellSelectionControllerExt class that is derived from the GridCellSelectionController to SfDataGrid’s SelectionController property to customize the navigation behavior of current cell when Tab or Enter key is pressed as illustrated in the following code example.
C#
public MainWindow() { InitializeComponent(); //Customized GridCellSelectionControllerExt class assigned to SfDataGrid’s SelectionController this.sfDataGrid.SelectionController = new GridCellSelectionControllerExt(sfDataGrid); }
The different position of selected range is initialized while dragging selection in SfDataGrid .The ProcessDragSelection() virtual method is invoked while dragging selection in SfDataGrid. You can initialize the position of selected range by overriding the ProcessDragSelection() as illustrated in the following code example.
C#
protected override void ProcessDragSelection(MouseEventArgs args, RowColumnIndex rowColumnIndex) { base.ProcessDragSelection(args, rowColumnIndex); //Initialize the range while dragging selection SetRange(); }
In the above code example, the SetRange() private method is invoked and the Top, Left, Right, and Bottom position of selected range is initialized as illustrated in the following code example.
C#
//SetRange() method for maintaining the Top , Bottom ,Left, Right position of selected region private void SetRange() { //Initialize the selected range position Top,Left,Right,Bottom _left = this.PressedRowColumnIndex.ColumnIndex; _right = this.CurrentCellManager.CurrentCell.ColumnIndex; _top = this.PressedRowColumnIndex.RowIndex; _bottom = this.CurrentCellManager.CurrentCell.RowIndex; }
You can customize the Enter and Tab key behavior of SfDataGrid by using ProcessKeyDown() virtual method of GridCellSelctionController as illustrated in the following code example.
C#
protected override void ProcessKeyDown(System.Windows.Input.KeyEventArgs args) { //If the current cell is null , return to end of the process if (this.CurrentCellManager.CurrentCell == null) return; //Get the current cell row and column index var rowIndex = this.CurrentCellManager.CurrentCell.RowIndex; var columnIndex = this.CurrentCellManager.CurrentCell.ColumnIndex; RowColumnIndex rowcolumnindex = new RowColumnIndex(); //If the current cell is not with in the selected range, the default key navigation behavior is processed if(!CheckWithInRange()) { base.ProcessKeyDown(args); ResetRange(); return; } //Customized behavior for Enter and Tab key //Check whether the pressed key is Tab or Enter key and customize its behavior //Customized behavior is processed only with in the selected ranges only if (args.Key == Key.Tab) { } //Customized behavior for Enter key else if (args.Key == Key.Enter ) { } else { //Default behavior processed for other key navigation base.ProcessKeyDown(args); } }
In the above code example, the default behavior is processed for Enter and Tab key navigation, when the current cell is not available with in selected range. By using CheckWithInRange() private method, you can identify whether the current cell is at selected range or out of the selected range as illustrated in the following code example.
C#
private bool CheckWithInRange() { //Check whether the current selected cell is within the position of selected range. if ((Top < this.CurrentCellManager.CurrentCell.RowIndex || Top == this.CurrentCellManager.CurrentCell.RowIndex)&& !(Top > this.CurrentCellManager.CurrentCell.RowIndex) && (Bottom > this.CurrentCellManager.CurrentCell.RowIndex || Bottom == this.CurrentCellManager.CurrentCell.RowIndex) &&!(Bottom < this.CurrentCellManager.CurrentCell.RowIndex) &&(Right > this.CurrentCellManager.CurrentCell.ColumnIndex || Right == this.CurrentCellManager.CurrentCell.ColumnIndex) && !(Right < this.CurrentCellManager.CurrentCell.ColumnIndex) && !(Left > this.CurrentCellManager.CurrentCell.ColumnIndex) && (Left <= this.CurrentCellManager.CurrentCell.ColumnIndex) ) { return true; } return false; }
Once the current cell is clicked out of the range, it is not considered as selected range and the position of selected range is reset to default value, then the default navigation and selection behavior is processed.
The position of selected range is reset by using ResetRange() private method as illustrated in the following code example.
C#
private void ResetRange() { //Reset the selected range _left = 0; _right = 0; _top = 0; _bottom = 0; }
The following code example illustrates on how to customize the navigation behavior of current cell when the Tab key is pressed in ProcessKeyDown virtual method of GridCellSelectionController.
C#
if (args.Key == Key.Tab) { //Check whether the current cell is placed at end of the right and bottom of selected region if (Right <= columnIndex && Bottom <= rowIndex) { //Need to move the current cell to top most left of the selected region rowcolumnindex.RowIndex = Top; rowcolumnindex.ColumnIndex = Left; this.MoveCurrentCell(rowcolumnindex, false); this.CurrentCellManager.ScrollInViewFromLeft(rowcolumnindex.ColumnIndex); args.Handled = true; return; } //Check whether the current cell is navigated within the selected region of Right position else if (Right > columnIndex) { //Move the current cell navigation to next column on same row within the selected region rowcolumnindex.ColumnIndex = columnIndex + 1; rowcolumnindex.RowIndex = rowIndex; this.MoveCurrentCell(rowcolumnindex, false); this.CurrentCellManager.ScrollInViewFromLeft(rowcolumnindex.ColumnIndex); args.Handled = true; return; } //It is fired ,when the current cell is at the end of the column of selected region else { //Move the current cell to next row at left position of selected region rowcolumnindex.RowIndex = rowIndex + 1; rowcolumnindex.ColumnIndex = Left; this.MoveCurrentCell(rowcolumnindex, false); this.CurrentCellManager.ScrollInViewFromLeft(rowcolumnindex.ColumnIndex); args.Handled = true; return; } }
The following code example illustrates on how to customize the navigation behavior of current cell when the Enter key is pressed in ProcessKeyDown virtual method of GridCellSelectionController.
C#
//Customized behavior for Enter key else if (args.Key == Key.Enter) { //Check whether the current cell is moved within the selected region if (Bottom > rowIndex && Right >= columnIndex) { //Move the current cell to next row and same column of selected region rowcolumnindex.RowIndex = rowIndex + 1; rowcolumnindex.ColumnIndex = columnIndex; this.MoveCurrentCell(rowcolumnindex, false); args.Handled = true; return; } //Check whether the current cell reached end of the row of selected region else if (Bottom <= rowIndex && Right != columnIndex) { //Then move the current cell to next top row of the column in selected region rowcolumnindex.RowIndex = Top; rowcolumnindex.ColumnIndex = columnIndex + 1; this.MoveCurrentCell(rowcolumnindex, false); this.DataGrid.ScrollInView(rowcolumnindex); args.Handled = true; return; } //Check whether the current cell reached end of bottom and right position of selected region else if (Bottom <= rowIndex && Right <= columnIndex) { //Then move the current cell to top most left position of the selected region rowcolumnindex.RowIndex = Top; rowcolumnindex.ColumnIndex = Left; this.MoveCurrentCell(rowcolumnindex, false); this.DataGrid.ScrollInView(rowcolumnindex); args.Handled = true; return; } }
By using HandlePointerOperations (), you can clear the position of selected range when the current cell is clicked without pressing Control key.
In SfDataGrid, the selection is removed when the already selected cell is selected again by using Control key. But in Excel, the selection is maintained. In this case, add selection externally to that cell by using AddSelection() method as illustrated in the following code example.
C#
public override void HandlePointerOperations(GridPointerEventArgs args, RowColumnIndex rowColumnIndex) { base.HandlePointerOperations(args, rowColumnIndex); if (args.Operation == PointerOperation.Released) { //Need to reset the range when the selected range cleared if(!SelectionHelper.CheckControlKeyPressed()&&this.GetSelectedCells().Count==1) { ResetRange(); } //Check the current cell with in the range if (CheckWithInRange()) { //Need to add the selection for current cell like in excel List<object> addedItems = new List<object>(); var GridCellInfo = this.DataGrid.GetGridCellInfo(rowColumnIndex); addedItems.Add(GridCellInfo); this.AddSelection(rowColumnIndex, addedItems); } } }
Sample Links