microsoft / microsoft/WinAppVSCE

[Feature]: XAML Visualizer

Open
#54 0 comments 0 reactions 1 assignee View on GitHub

@chiaramooney is already working on this.

Since Jul 20, 2026.

enhancement
Dominant language
TypeScript
Stars
13
Forks
3
Avg merge
6d 1h
Merged PRs (30d)
11

Description

1. Summary

A read-only, real-time preview of a XAML page/control rendered next to the editor. As the developer edits XAML, a preview pane updates live to show the rendered UI, with light/dark/high-contrast theme switching, device/size presets, and zoom.

Image

2. Problem / motivation

WinUI 3 XAML has no live preview in VS Code — you must build and run to see layout, and even VS's XAML Designer for WinUI 3 is limited. Iterating on spacing, styles, and control composition means a build-run-look-repeat loop measured in tens of seconds. A live visualiser collapses that to instant feedback, which is the highest-frequency inner-loop activity in UI work. This is table stakes for Avalonia and Uno in VS Code today; WinUI needs parity.

3. Similar Products

Tool Approach
Avalonia Previewer (VS Code) Out-of-process design-time host renders the control in isolation with design-time data; editor streams XAML deltas.
Uno Hot Design / Hot Reload (VS Code) Renders inside the running app on any target; editor is a relay.
VS XAML Live Preview Shows the running app's UI in an IDE pane.
VS XAML Designer (WPF/UWP) Design-time render surface; weak/absent for WinUI 3.

Takeaway: two industry patterns — design-time isolated render (Avalonia) vs running-app render (Uno/VS Live Preview). Does it make sense to do both?

4. Goals / non-goals

Goals

  • Live preview pane (side-by-side or separate tab) that re-renders on XAML edit, debounced.
  • Theme toggle: Light / Dark / High Contrast. Size presets.
  • Zoom / pan; DPI-accurate rendering; background/checkerboard for transparency.
  • Graceful error surface: when XAML can't render, show the parse/runtime error in the pane, keep last-good render.
  • Works in VS Code / Cursor / Windsurf (webview-based host; no editor-proprietary rendering).

Non-goals

  • Editing via the preview (drag/drop, selection→XAML) — that's C4.
  • Inspecting a running app's live tree — that's C6.
  • Pixel-perfect guarantee for every third-party/custom-drawn control (best-effort via the engine).

5. Proposed implementation

VS Code Webview (preview pane)  ◀──img/stream──  C3 host (extension)
        │  theme/size/zoom UI                         │  spawns + supervises
        │  error overlay                               ▼
        └──────────────── XAML text + context ──▶  B4c design-time render engine
                                                     (renders control/page → frames/bitmap,
                                                      resolves types/resources/themes)
  • Render source (B4c): the engine loads the XAML in a design-time context, resolves the project's types/resources/styles (shared with C1's type system), and produces rendered output — either a bitmap per change or a lightweight frame stream. C3 does not render XAML itself.
  • Transport: the engine runs as a child process; communicate over a local socket/stdio JSON protocol (send: XAML doc + project context + theme/size; receive: image + hit-test metadata + errors). Metadata (element bounds) is optional for C3 but forward-compatible with C4.
  • Host/UI: a VS Code webview shows the image with a toolbar (theme, size, zoom, refresh). The extension watches the active XAML doc, debounces edits (~150–300 ms), and forwards them.
  • Project context: obtain refs/resource dictionaries/TFM from the winapp CLI project model (B); reuse restore output so custom controls and StaticResources resolve.

6. API / contribution surface

"contributes": {
  "commands": [
    { "command": "winapp.xaml.openPreview", "title": "WinApp: Open XAML Preview", "category": "WinApp" },
    { "command": "winapp.xaml.openPreviewToSide", "title": "WinApp: Open XAML Preview to the Side", "category": "WinApp" }
  ],
  "menus": { "editor/title": [{ "command": "winapp.xaml.openPreviewToSide", "when": "resourceExtname == .xaml", "group": "navigation" }] },
  "configuration": {
    "winapp.xaml.preview.theme": { "enum": ["light","dark","highContrast"], "default": "dark" },
    "winapp.xaml.preview.defaultSize": { "type": "string", "default": "1280x720" },
    "winapp.xaml.preview.autoRefresh": { "type": "boolean", "default": true },
    "winapp.xaml.preview.refreshDebounceMs": { "type": "number", "default": 200 }
  }
}

Design-time render protocol (host ↔ B4c), illustrative:

// → render request
{ "op":"render", "uri":"MainWindow.xaml", "text":"<Grid…", "project":"CounterApp.csproj",
  "theme":"dark", "size":{"w":375,"h":720}, "dpi":1.25, "wantHitTest":false }
// ← render result
{ "op":"frame", "png":"<base64|shared-mem handle>", "width":375, "height":720,
  "diagnostics":[{ "severity":"error", "message":"Cannot find resource 'TitleStyle'", "line":7 }] }

7. Design tradeoffs & alternatives

  • Design-time render vs running-app preview. Design-time (this spec) gives feedback with no build/run and no identity/cert friction, but can diverge from runtime for code-driven UI. Running-app preview is truest but slow to start.
  • Bitmap-per-change vs frame stream. Bitmaps are simplest and plenty for a preview; a stream enables animations/interaction later (C4). Start with debounced bitmaps; design the protocol to allow streaming.
  • Isolation scope: control vs whole window. Rendering a single UserControl/Page is fast and matches Avalonia; whole-window may need app resources. Support page/control first.

8. Dependencies & risks

  • Hard dependency on B4c. Without the design-time render engine, C3 cannot exist; C3's timeline is gated by B4c. This spec covers only the host/UI/protocol side.

9. Open questions

  1. What exactly does B4c emit — bitmaps, a retained visual tree, or a frame stream — and what's its API/timeline?
  2. Page/control isolation vs full-window preview for v1?
  3. Does implementing both hot reload and a visualizer make sense? Is there business need for both?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.