Skip to content

Complete multi-row drag selection behavior#316

Open
wieslawsoltes wants to merge 1 commit into
masterfrom
agent/issue-296-multi-row-drag
Open

Complete multi-row drag selection behavior#316
wieslawsoltes wants to merge 1 commit into
masterfrom
agent/issue-296-multi-row-drag

Conversation

@wieslawsoltes

Copy link
Copy Markdown
Owner

Summary

Completes the multi-row drag gesture so selected rows remain intact while drag intent is being determined, while preserving normal click selection behavior when no drag occurs.

  • defers selection collapse when pointer press starts on an already selected row in an extended full-row multi-selection
  • cancels the deferred collapse as soon as the row drag crosses its threshold, allowing the existing drag-info pipeline to include every selected row
  • applies the normal single-row click selection on pointer release when no drag started
  • supports both whole-row and row-header drag surfaces
  • centralizes row-drag eligibility so read-only, disabled, add-new, and edit states do not suppress ordinary selection when a row drag cannot start
  • documents the press/threshold/release contract

Problem analysis

The repository already had the two core pieces needed for multi-row drag:

  1. DataGridRowDragDropController.TryCreateDragInfo() uses all selected rows when the pressed row is selected and DragSelectedRows is enabled.
  2. The selection handler preserves a multi-selection on pointer press when SuppressSelectionDragFromDragHandle is enabled.

The remaining gap was pointer-release behavior. Preserving selection unconditionally on press solved drag startup, but it also meant a simple click on one selected row never performed the usual selection collapse. The issue discussion correctly identifies the required sequencing: preserve on press, decide between click and drag, then apply click selection on release only if the drag threshold was not crossed.

Implementation

DataGrid now owns a small deferred row-selection record containing the pointer id, row slot, column surface, and original press event.

  • row/cell press records the deferred selection only when a built-in row drag is actually eligible
  • the row drag controller completes it on matching pointer release
  • drag startup and every pointer-controller reset path cancel it
  • completion reuses the existing pointer selection pipeline, keeping currency, edit commit, selection notifications, and bound SelectedItems behavior consistent

The controller and selection code share one CanStartRowDragGesture() predicate so gesture suppression cannot diverge from actual drag eligibility.

No view code-behind, reflection, static state, or new public API is introduced.

Tests

Headless coverage verifies:

  • whole-row press keeps the complete selection until release
  • whole-row release without drag collapses to the clicked row
  • canceled/deferred selection remains multi-selected, matching drag startup behavior
  • row-header press/release follows the same contract
  • read-only grids do not defer selection because row drag cannot start
  • existing suppression-disabled behavior remains unchanged

Validation performed:

  • mouse-selection + row-drag controller lane: 96 passed
  • complete unit suite: 2,252 passed
  • production build, net8.0: 0 errors
  • production build, net10.0: 0 errors

Fixes #296

@wieslawsoltes

Copy link
Copy Markdown
Owner Author

Self-review completed. I reviewed deferred selection lifecycle, pointer cancellation, drag-start gating, multi-selection behavior, and regression coverage; no additional actionable findings were found. All six CI checks are successful, the branch is synchronized, and git diff --check is clean. This PR is ready for review.

@wieslawsoltes
wieslawsoltes marked this pull request as ready for review July 15, 2026 00:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DatagridSample Row Drag & Drop is not support multi rows Drag

1 participant