Skip to content
Development
Skill

/winui-wpf-migration

Migrate WPF applications to WinUI 3 — namespace replacement (System.Windows → Microsoft.UI.Xaml), control mapping (DataGrid→ListView, WrapPanel→ItemsRepeater, TabControl→TabView), threading (Dispatcher→DispatcherQueue), imaging (System.Drawing→BitmapImage), MVVM conversion to

From plugin
win-dev-skills
3758 skills1 agent
Install
$ npx -y skills add microsoft/win-dev-skills --skill winui-wpf-migration --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/winui-wpf-migration

Context preview

The summary Claude sees to decide when to auto-load this skill.

Migrate WPF applications to WinUI 3 — namespace replacement (System.Windows → Microsoft.UI.Xaml), control mapping (DataGrid→ListView, WrapPanel→ItemsRepeater, TabControl→TabView), threading (Dispatcher→DispatcherQueue), imaging (System.Drawing→BitmapImage), MVVM conversion to

SKILL.md

winui-wpf-migration.SKILL.md
name: winui-wpf-migration
description: "Migrate WPF applications to WinUI 3 — namespace replacement (System.Windows → Microsoft.UI.Xaml), control mapping (DataGrid→ListView, WrapPanel→ItemsRepeater, TabControl→TabView), threading (Dispatcher→DispatcherQueue), imaging (System.Drawing→BitmapImage), MVVM conversion to CommunityToolkit.Mvvm, and DynamicResource→ThemeResource. Use when converting WPF code, replacing WPF namespaces, or fixing migration build errors."

Migration Process

Step 1: Audit the WPF Source

Before writing code, inventory WPF-specific APIs:

# Find all WPF namespace usage
Select-String -Path (Get-ChildItem -Recurse -Filter "*.cs" | Where-Object { $_.FullName -notlike "*\obj\*" }) -Pattern "System\.Windows\." | Select-Object -Property Filename, LineNumber, Line

List: WPF controls used, custom MVVM framework, imaging APIs, threading patterns, Win32 interop.

Step 2: Create WinUI 3 Project and Align Namespaces

dotnet new winui-mvvm -n <AppName>

Immediately set `<RootNamespace>` in `.csproj` to match the WPF namespace. Update `x:Class` in `App.xaml`, `MainWindow.xaml` and their code-behind files. Build to verify before porting any code.

Step 3: Replace Namespaces

| WPF | WinUI 3 | |-----|---------| | `System.Windows` | `Microsoft.UI.Xaml` | | `System.Windows.Controls` | `Microsoft.UI.Xaml.Controls` | | `System.Windows.Media` | `Microsoft.UI.Xaml.Media` | | `System.Windows.Input` | `Microsoft.UI.Xaml.Input` | | `System.Windows.Data` | `Microsoft.UI.Xaml.Data` | | `System.Windows.Threading.Dispatcher` | `Microsoft.UI.Dispatching.DispatcherQueue` | | `PresentationCore` / `PresentationFramework` | Remove entirely |

Step 4: Replace Controls

| WPF Control | WinUI 3 Equivalent | |------------|-------------------| | `DataGrid` | `ListView` with Grid column headers | | `WrapPanel` | `ItemsRepeater` + `UniformGridLayout` | | `TabControl` | `TabView` | | `StatusBar` | `Grid` row at bottom with `TextBlock` elements | | `Menu` / `MenuItem` | `MenuBar` / `MenuBarItem` / `MenuFlyoutItem` | | `ToolBar` | `CommandBar` | | `Expander` (custom) | `Expander` (built-in) |

Step 5: Replace Threading

// WPF
Application.Current.Dispatcher.Invoke(() => { /* UI work */ });

// WinUI 3
dispatcherQueue.TryEnqueue(() => { /* UI work */ });

Get via `DispatcherQueue.GetForCurrentThread()`. No `Application.Current.Dispatcher` in WinUI 3.

Step 6: Replace Imaging

**Critical:** `PresentationCore.dll` and `System.Windows.Media.Imaging` crash the WinUI XAML compiler. This is an architectural incompatibility — no workaround exists.

  • Remove ALL `System.Windows.Media.Imaging` references at migration start
  • Replace with `Windows.Graphics.Imaging` (WinRT) or `Microsoft.UI.Xaml.Media.Imaging.BitmapImage`
  • Do NOT add `<UseWPF>true</UseWPF>` — it silently corrupts the build
  • If heavy imaging code exists, migrate it early (step 2, not step 7)

Step 7: Replace MVVM Framework

Delete custom `ObservableObject`/`RelayCommand`/`DelegateCommand`. Use CommunityToolkit.Mvvm:

  • `INotifyPropertyChanged` base → `ObservableObject` with `[ObservableProperty]` partial properties
  • Custom `RelayCommand` → `[RelayCommand]` attribute
  • `{Binding}` → `{x:Bind Mode=OneWay}`
  • `DynamicResource` → `{ThemeResource}`

Step 8: Replace Resources

  • `.resx` → `.resw` (copy + rename to `Strings\en-us\`)
  • `{x:Static}` → `x:Uid` for localized strings
  • `Properties.Resources.Key` → `ResourceLoader.GetString("Key")`

Critical Rules

  • ❌ NEVER reference `PresentationCore`, `PresentationFramework`, or `System.Windows.Controls` assemblies
  • ❌ NEVER add `<UseWPF>true</UseWPF>` or `<WindowsPackageType>None</WindowsPackageType>`
  • ❌ NEVER delete `Package.appxmanifest`
  • ❌ NEVER overwrite `App.xaml` / `App.xaml.cs` — merge WPF code into the WinUI 3 boilerplate
  • ✅ Always use `winapp run` to launch — never run the .exe directly
  • ✅ Break migration into file-level tasks — not one massive rewrite

Post-Migration Validation

# Check for remaining WPF references (should return nothing)
Select-String -Path (Get-ChildItem -Recurse -Filter "*.cs" | Where-Object { $_.FullName -notlike "*\obj\*" }) -Pattern "System\.Windows\."

# Verify packaging preserved
Test-Path "Package.appxmanifest"  # should be True

# Build and run
.\BuildAndRun.ps1
Read more
Ships withwin-dev-skills

A GitHub Copilot, Claude Code, and OpenAI Codex plugin for building native Windows apps with WinUI 3 and the Windows App SDK to cover the end-to-end inner loop: scaffold → design → build → run → test → package → ship.

Get the whole plugin

Other skills on win-dev-skills.