Skip to content

feat(xaml-designer): bidirectional canvas↔code selection sync — untested, needs QA #210

@abbaye

Description

@abbaye

Feature

Bidirectional selection sync between the XAML Designer canvas and the code editor (VS-like).

Commits: 73bca10e, 6e553bc9 on branch DebugNewFeatures


What was implemented

Canvas → Code

  • Clicking an element on the canvas navigates the code editor caret to the element's opening tag line.
  • Uses XamlSourceLocationService.FindElementStartLine (XDocument + IXmlLineInfo).

Code → Canvas

  • Moving the caret in the code editor (no active text selection) selects the matching element on the canvas.
  • Debounced at 150ms via _codeToCanvasSyncTimer; fires on both CaretMoved (line changes) and SelectionChanged (same-line clicks).
  • Uses XamlSourceLocationService.FindUidAtLine (XmlReader + IXmlLineInfo, pre-order UID traversal).

Quality fixes (commit 6e553bc9)

  • Post-render preserve selection: canvas no longer loses selection after every 500ms debounce re-render.
  • Silent selection API: SelectElement(suppressEvent:true) / SelectElementByUid(suppressEvent:true) for programmatic restores.
  • ApplyXamlToCode guard: _isSyncingSelection=true prevents LoadFromString caret-reset from triggering spurious root-element sync.
  • Caret theft prevention: skip NavigateTo when code editor is already on the correct line.

Test scenarios to validate

  • Click Button on canvas → code editor caret jumps to <Button line
  • Press Escape on canvas (select parent) → code editor moves to parent's line
  • Click on <Button in code editor → Button gets selection adorner on canvas
  • Click same line multiple times → canvas still re-syncs correctly
  • Edit Width="100" → canvas re-renders → element stays selected (not deselected)
  • Drag resize handle, release → code updates → canvas re-renders → element stays selected, code caret not stolen
  • Click Button on canvas twice → code editor does NOT move on 2nd click (already on line)
  • Rapid keyboard navigation (10 lines) → canvas syncs once after 150ms idle
  • Switch to Code-Only mode → no canvas sync fires
  • Switch back to Split mode → sync resumes on next caret move
  • Undo/Redo after design operation → selection preserved, no feedback loop

Known limitations / risk areas

  • UID numbering uses raw XAML (not sanitized). If SanitizeForPreview ever removes entire elements (currently only strips attributes), UIDs would desync.
  • Single-line compact XAML (<Grid><Button/></Grid>) always syncs to the last (deepest) element on the line — acceptable behavior.
  • SelectionChanged subscription may fire during text drag-select; guarded by Selection.IsEmpty check.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions