How to prevent selecting the Group Header when changing selection with Down/Up arrow keys?

We want the user to be able to move the row selection with the up/down arrow keys. When having a grouped display the selection also is selecting the group header row, from a users perspective the row selection is "disappearing" when he hits a group row when moving the row selection up/down with the arrow keys.

So how can we skip the selection of the group header and jump with the selection to the next data row (first row in next group) when moving down with the down arrow key. Or the last data row in the previous group when moving up with the up arrow key?. Or how do we extend the selection controller to only allow to select data rows and get the same behavior as intended?

Thanks for any suggestions.


1 Reply

VS Vijayarasan Sivanandham Syncfusion Team October 18, 2021 02:02 PM UTC

Hi Michael Pillwax,

Thank you for contacting Syncfusion Support.

By default, the group summary and caption summary rows will be selected on both mouse click and arrow keys navigation. You can skip the pointer selection and arrow key navigation for these summary rows by creating a custom SelectionController and overriding the HandlePointerOperations  and ProcessKeyDown methods respectively. 
this.sfDataGrid.SelectionController = new CustomGridSelectionController(this.sfDataGrid); 
 
public class CustomGridSelectionController : GridSelectionController 
{ 
        public CustomGridSelectionController(SfDataGrid dataGrid) : base(dataGrid) 
        { 
 
        } 
 
        public override void HandlePointerOperations(GridPointerEventArgs args, RowColumnIndex rowColumnIndex) 
        { 
            if (this.IsCaptionSummaryRow(rowColumnIndex.RowIndex) || this.IsGroupSummaryRow(rowColumnIndex.RowIndex)) 
                return; 
            base.HandlePointerOperations(args, rowColumnIndex); 
        } 
 
        bool IsCaptionSummaryRow(int rowIndex) 
        { 
            var startIndex = this.DataGrid.ResolveStartIndexBasedOnPosition(); 
            var record = this.DataGrid.View.TopLevelGroup != null ? this.DataGrid.View.TopLevelGroup.DisplayElements[rowIndex - startIndex] : null; 
            return record != null && record is Group; 
        } 
 
        bool IsGroupSummaryRow(int rowIndex) 
        { 
            var startIndex = this.DataGrid.ResolveStartIndexBasedOnPosition(); 
            var record = this.DataGrid.View.TopLevelGroup !=null? this.DataGrid.View.TopLevelGroup.DisplayElements[rowIndex - startIndex]:null; 
            return record != null && record is SummaryRecordEntry; 
 
        } 
 
        protected override void ProcessKeyDown(KeyEventArgs args) 
        { 
            if (args.Key == Key.Up) 
            { 
                this.MoveCurrentCell(new RowColumnIndex(this.GetPreviousRecordRowIndex(this.CurrentCellManager.CurrentCell.RowIndex), this.CurrentCellManager.CurrentCell.ColumnIndex)); 
            } 
            else if (args.Key == Key.Down) 
            { 
                this.MoveCurrentCell(new RowColumnIndex(this.GetNextRecordRowIndex(this.CurrentCellManager.CurrentCell.RowIndex), this.CurrentCellManager.CurrentCell.ColumnIndex)); 
            } 
            else 
                base.ProcessKeyDown(args); 
        }         
 
        private int GetNextRecordRowIndex(int currentRowIndex) 
        { 
            int nextRecordRowIndex = currentRowIndex + 1; 
 
            if (nextRecordRowIndex > this.GetLastRowIndex(this.DataGrid)) 
                return this.CurrentCellManager.CurrentCell.RowIndex; 
 
            if (!this.IsCaptionSummaryRow(nextRecordRowIndex) && !this.IsGroupSummaryRow(nextRecordRowIndex)) 
                return nextRecordRowIndex; 
            else 
                return GetNextRecordRowIndex(nextRecordRowIndex); 
        } 
 
        private int GetLastRowIndex(SfDataGrid dataGrid) 
        { 
            if (DataGrid.GetRecordsCount() == 0) 
                return -1; 
            var footerCount = DataGrid.GetUnBoundRowsCount(UnBoundRowsPosition.Bottom, true); 
            int count = 0; 
            int index = DataGrid.GetVisualContainer().RowCount - (DataGrid.GetTableSummaryCount(TableSummaryRowPosition.Bottom) + footerCount + 1); 
            if (DataGrid.AddNewRowPosition == AddNewRowPosition.Bottom) 
                index -= 1; 
            if (DataGrid.FilterRowPosition == FilterRowPosition.Bottom) 
                index -= 1; 
            for (int start = index; start >= 0; start--) 
           { 
                if (!DataGrid.GetVisualContainer().RowHeights.GetHidden(start, out count)) 
                    return start; 
            } 
            return index; 
        } 
 
        private int GetPreviousRecordRowIndex(int currentRowIndex) 
        { 
            int previousRecordRowIndex = currentRowIndex - 1; 
 
            if (previousRecordRowIndex <= 0) 
                return this.CurrentCellManager.CurrentCell.RowIndex; 
 
            if (!this.IsCaptionSummaryRow(previousRecordRowIndex) && !this.IsGroupSummaryRow(previousRecordRowIndex)) 
                return previousRecordRowIndex; 
            else 
                return GetPreviousRecordRowIndex(previousRecordRowIndex); 
        } 
 
        protected override void ProcessOnGroupChanged(GridGroupingEventArgs args) 
        { 
            if (this.DataGrid.SelectionMode == GridSelectionMode.None) 
                return; 
            this.DataGrid.ClearSelections(false); 
        } 
} 

Sample Link: https://www.syncfusion.com/downloads/support/forum/169682/ze/Sample-1986134671

For more information related to Customizing Selection Behaviors, please refer the user guide documentation,

UG Link:
https://help.syncfusion.com/wpf/datagrid/selection#customizing-selection-behaviors

KB Link
https://www.syncfusion.com/kb/6650/how-to-clear-the-selection-while-grouping-or-ungrouping-in-wpf-datagrid-sfdatagrid

Please let us know if you have any concerns in this. 
 
Regards, 
Vijayarasan S 


Loader.
Up arrow icon