Overview

Namespace: TheTechIdea.Beep.Winform.Controls.GridX.Selection
The grid selection system uses the Strategy pattern with 6 implementations of ISelectionStrategy (all internal sealed, all singletons via public static readonly ... Instance). Each strategy handles cell clicks, column-header clicks, keyboard navigation, and selection clearing independently. The active strategy is selected by the grid's SelectionMode property.

All strategies receive a SelectionContext object that provides grid state access and a StrategyState dictionary for storing strategy-specific data (e.g., anchor position for range selection in MultiCellStrategy).

ISelectionStrategy Interface

internal interface ISelectionStrategy
{
    void HandleCellClick(SelectionContext context,
        int row, int col, bool ctrlPressed, bool shiftPressed);

    void HandleColumnHeaderClick(SelectionContext context,
        int col, bool ctrlPressed, bool shiftPressed);

    void HandleKeyboardNavigation(SelectionContext context,
        int deltaRow, int deltaCol);

    void ClearSelection(SelectionContext context);
}

SelectionContext

Lightweight context object passed to every strategy method. Thread-unsafe — designed for single UI thread use only.

MemberTypeDescription
GridBeepGridProThe grid instance
SelectionGridSelectionHelperHelper for state manipulation (SelectCell, SelectRow)
StrategyStateDictionary<string,object>Bag for strategy-specific data (anchors, ranges, last-selected)
RowCountintCurrent rows from Grid.Data.Rows.Count
ColumnCountintCurrent columns from Grid.Data.Columns.Count
IsValidCell(r,c)boolBoundary check: 0 ≤ row < RowCount, 0 ≤ col < ColumnCount
SetActiveCell(r,c)voidSets active cell via Selection.SelectCell(row, col)
SetRowSelected(r, bool)voidSets Data.Rows[row].IsSelected
SetCellSelected(r,c, bool)voidSets per-cell IsSelected on the data cell
ClearAllRowSelection()voidIterates all rows: IsSelected = false
ClearAllCellSelection()voidIterates all cells: IsSelected = false
RaiseRowSelectionChanged(r)voidFires the grid's row selection changed event
EnsureVisible()voidScrolls to active cell's row/column

CellSelectionStrategy

Single cell selection. public static readonly CellSelectionStrategy Instance.

  • HandleCellClick: Clears all cell AND row selection, then selects only the clicked cell via SetActiveCell
  • HandleColumnHeaderClick: No-op (column headers ignored)
  • HandleKeyboardNavigation: Moves single cell by (deltaRow, deltaCol), clamped to grid bounds via IsValidCell
  • ClearSelection: Clears all row and cell selection state

RowSelectionStrategy

Full row selection. public static readonly RowSelectionStrategy Instance.

  • HandleCellClick: When Ctrl is pressed AND Grid.MultiSelect is true, toggles the clicked row's selection (additive). Otherwise clears all and selects the entire row (all columns marked selected).
  • HandleColumnHeaderClick: No-op
  • HandleKeyboardNavigation: Moves to next/previous row (deltaRow). Keeps the column index from Selection.ColumnIndex so the active cell stays in the same column.
  • ClearSelection: Clears all row and cell selection

MultiCellSelectionStrategy

Excel-style multi-cell with range selection. public static readonly MultiCellSelectionStrategy Instance. Uses StrategyState["MultiCellAnchor"] to store anchor (int Row, int Col).

  • HandleCellClick (Ctrl): Toggles the individual cell selection without clearing existing selection. Updates anchor.
  • HandleCellClick (Shift): Selects a rectangular range from the anchor (row1,col1) to the clicked cell (row2,col2). All cells in the rectangle are selected.
  • HandleCellClick (normal): Clears all, selects only the clicked cell, sets anchor.
  • HandleColumnHeaderClick (normal): Clears all, selects all cells in the target column.
  • HandleColumnHeaderClick (Ctrl/Shift): Adds the column's cells to existing selection.
  • HandleKeyboardNavigation: Moves single-cell selection, clears others, updates anchor.
  • Private helpers: ClearAndSelect, SetAnchor(row,col) stores tuple in StrategyState, GetAnchor retrieves (int Row, int Col)?.

MultiRowSelectionStrategy

Multi-row with Shift+range expansion from anchor. Same structure as RowSelectionStrategy but Shift+click selects a continuous row range from anchor to clicked row. Ctrl+click toggles individual rows.

ColumnSelectionStrategy

Column-level selection. Clicking a column header selects all cells in that column. Shift+click expands to a contiguous column range. Ctrl+click modifies the column selection (adds/removes column).

Comparison Table

StrategyNormal ClickCtrl+ClickShift+ClickColumn ClickKeyboard
CellSelect cellSelect cellSelect cellNoneMove cell
RowSelect rowToggle rowSelect rowNoneMove row
MultiCellSelect cellToggle cellRange from anchorSelect columnMove cell
MultiRowSelect rowToggle rowRow rangeNoneMove row
ColumnSelect cellSelect cellSelect cellSelect columnMove cell

Code Examples

// Cell selection (default)
grid.SelectionMode = BeepGridSelectionMode.Cell;   // CellSelectionStrategy

// Full row selection
grid.SelectionMode = BeepGridSelectionMode.FullRow; // RowSelectionStrategy
grid.MultiSelect = true;  // Ctrl+click toggles rows

// Excel-style multi-cell
grid.SelectionMode = BeepGridSelectionMode.MultiCell; // MultiCellSelectionStrategy
// Now: Shift+drag for rectangular range, Ctrl+click for individual cells