Help us improve
Share bugs, ideas, or general feedback.
How this skill is triggered — by the user, by Claude, or both
Slash command
/winui:winui-wpf-migrationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Before writing code, inventory WPF-specific APIs:
Migrating desktop apps. WPF/WinForms to .NET 8+, WPF to WinUI or Uno, UWP to WinUI, decision matrix.
Migrates WPF apps from .NET Framework to .NET 6+, converting project files to SDK style, updating NuGet packages, and fixing compatibility issues for legacy upgrades.
Builds and runs WinUI 3 apps with project creation, package installation, and error diagnosis. Use when building, running, or fixing build errors in a WinUI 3 project.
Share bugs, ideas, or general feedback.
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.
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.
| 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 |
| 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) |
// WPF
Application.Current.Dispatcher.Invoke(() => { /* UI work */ });
// WinUI 3
dispatcherQueue.TryEnqueue(() => { /* UI work */ });
Get via DispatcherQueue.GetForCurrentThread(). No Application.Current.Dispatcher in WinUI 3.
Critical: PresentationCore.dll and System.Windows.Media.Imaging crash the WinUI XAML compiler. This is an architectural incompatibility — no workaround exists.
System.Windows.Media.Imaging references at migration startWindows.Graphics.Imaging (WinRT) or Microsoft.UI.Xaml.Media.Imaging.BitmapImage<UseWPF>true</UseWPF> — it silently corrupts the buildDelete custom ObservableObject/RelayCommand/DelegateCommand. Use CommunityToolkit.Mvvm:
INotifyPropertyChanged base → ObservableObject with [ObservableProperty] partial propertiesRelayCommand → [RelayCommand] attribute{Binding} → {x:Bind Mode=OneWay}DynamicResource → {ThemeResource}.resx → .resw (copy + rename to Strings\en-us\){x:Static} → x:Uid for localized stringsProperties.Resources.Key → ResourceLoader.GetString("Key")PresentationCore, PresentationFramework, or System.Windows.Controls assemblies<UseWPF>true</UseWPF> or <WindowsPackageType>None</WindowsPackageType>Package.appxmanifestApp.xaml / App.xaml.cs — merge WPF code into the WinUI 3 boilerplatewinapp run to launch — never run the .exe directly# 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