Use this skill when migrating UWP apps to WinUI 3 / Windows App SDK, or when verifying that generated code uses correct WinUI 3 APIs instead of legacy UWP patterns.
Namespace Changes
All Windows.UI.Xaml.* namespaces move to Microsoft.UI.Xaml.*:
UWP Namespace
WinUI 3 Namespace
Windows.UI.Xaml
Microsoft.UI.Xaml
Windows.UI.Xaml.Controls
Microsoft.UI.Xaml.Controls
Windows.UI.Xaml.Media
Microsoft.UI.Xaml.Media
Windows.UI.Xaml.Input
Microsoft.UI.Xaml.Input
Windows.UI.Xaml.Data
Microsoft.UI.Xaml.Data
Windows.UI.Xaml.Navigation
Microsoft.UI.Xaml.Navigation
Windows.UI.Xaml.Shapes
Microsoft.UI.Xaml.Shapes
Windows.UI.Composition
Microsoft.UI.Composition
Windows.UI.Input
Microsoft.UI.Input
Windows.UI.Colors
Microsoft.UI.Colors
Windows.UI.Text
Microsoft.UI.Text
Windows.UI.Core
Microsoft.UI.Dispatching (for dispatcher)
Top 3 Most Common Copilot Mistakes
1. ContentDialog Without XamlRoot
// ❌ WRONG — Throws InvalidOperationException in WinUI 3
var dialog = new ContentDialog
{
Title = "Error",
Content = "Something went wrong.",
CloseButtonText = "OK"
};
await dialog.ShowAsync();
// ✅ CORRECT — Set XamlRoot before showing
var dialog = new ContentDialog
{
Title = "Error",
Content = "Something went wrong.",
CloseButtonText = "OK",
XamlRoot = this.Content.XamlRoot // Required in WinUI 3
};
await dialog.ShowAsync();
2. MessageDialog Instead of ContentDialog
// ❌ WRONG — UWP API, not available in WinUI 3 desktop
var dialog = new Windows.UI.Popups.MessageDialog("Are you sure?", "Confirm");
await dialog.ShowAsync();
// ✅ CORRECT — Use ContentDialog
var dialog = new ContentDialog
{
Title = "Confirm",
Content = "Are you sure?",
PrimaryButtonText = "Yes",
CloseButtonText = "No",
XamlRoot = this.Content.XamlRoot
};
var result = await dialog.ShowAsync();
if (result == ContentDialogResult.Primary)
{
// User confirmed
}
3. CoreDispatcher Instead of DispatcherQueue
// ❌ WRONG — CoreDispatcher does not exist in WinUI 3
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
StatusText.Text = "Done";
});
// ❌ WRONG — UWP style, no window handle
var picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".txt");
var file = await picker.PickSingleFileAsync();
// ✅ CORRECT — Initialize with window handle
var picker = new FileOpenPicker();
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);
WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd);
picker.FileTypeFilter.Add(".txt");
var file = await picker.PickSingleFileAsync();
Threading Migration
UWP Pattern
WinUI 3 Equivalent
CoreDispatcher.RunAsync(priority, callback)
DispatcherQueue.TryEnqueue(priority, callback)
Dispatcher.HasThreadAccess
DispatcherQueue.HasThreadAccess
CoreDispatcher.ProcessEvents()
No equivalent — restructure async code
CoreWindow.GetForCurrentThread()
Not available — use DispatcherQueue.GetForCurrentThread()
Key difference: UWP uses ASTA (Application STA) with built-in reentrancy blocking. WinUI 3 uses standard STA without this protection. Watch for reentrancy issues when async code pumps messages.
Background Tasks Migration
// ❌ WRONG — UWP IBackgroundTask
public sealed class MyTask : IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance) { }
}
// ✅ CORRECT — Windows App SDK AppLifecycle
using Microsoft.Windows.AppLifecycle;
// Register for activation
var args = AppInstance.GetCurrent().GetActivatedEventArgs();
if (args.Kind == ExtendedActivationKind.AppNotification)
{
// Handle background activation
}
All GetForCurrentView() patterns are unavailable in WinUI 3 desktop apps:
UWP API
WinUI 3 Replacement
UIViewSettings.GetForCurrentView()
Use AppWindow properties
ApplicationView.GetForCurrentView()
AppWindow.GetFromWindowId(windowId)
DisplayInformation.GetForCurrentView()
Win32 GetDpiForWindow() or XamlRoot.RasterizationScale
CoreApplication.GetCurrentView()
Not available — track windows manually
SystemNavigationManager.GetForCurrentView()
Handle back navigation in NavigationView directly
Testing Migration
UWP unit test projects do not work with WinUI 3. You must migrate to the WinUI 3 test project templates.
UWP
WinUI 3
Unit Test App (Universal Windows)
Unit Test App (WinUI in Desktop)
Standard MSTest project with UWP types
Must use WinUI test app for Xaml runtime
[TestMethod] for all tests
[TestMethod] for logic, [UITestMethod] for XAML/UI tests
Class Library (Universal Windows)
Class Library (WinUI in Desktop)
// ✅ WinUI 3 unit test — use [UITestMethod] for any XAML interaction
[UITestMethod]
public void TestMyControl()
{
var control = new MyLibrary.MyUserControl();
Assert.AreEqual(expected, control.MyProperty);
}
Key: The [UITestMethod] attribute tells the test runner to execute the test on the XAML UI thread, which is required for instantiating any Microsoft.UI.Xaml type.
Migration Checklist
Replace all Windows.UI.Xaml.* using directives with Microsoft.UI.Xaml.*
Replace Windows.UI.Colors with Microsoft.UI.Colors
Replace CoreDispatcher.RunAsync with DispatcherQueue.TryEnqueue
Replace Window.Current with App.MainWindow static property
Add XamlRoot to all ContentDialog instances
Initialize all pickers with InitializeWithWindow.Initialize(picker, hwnd)
Replace MessageDialog with ContentDialog
Replace ApplicationView/CoreWindow with AppWindow
Replace CoreApplicationViewTitleBar with AppWindowTitleBar
Replace all GetForCurrentView() calls with AppWindow equivalents
Update interop for Share and Print managers
Replace IBackgroundTask with AppLifecycle activation
Update project file: TFM to net10.0-windows10.0.22621.0, add <UseWinUI>true</UseWinUI>
Migrate unit tests to Unit Test App (WinUI in Desktop) project; use [UITestMethod] for XAML tests
Test both packaged and unpackaged configurations
1---2name: winui3-migration-guide3description: Maps legacy UWP APIs to correct Windows App SDK equivalents with before/after code snippets for migrating to WinUI 3.4---56# WinUI 3 Migration Guide78Use this skill when migrating UWP apps to WinUI 3 / Windows App SDK, or when verifying that generated code uses correct WinUI 3 APIs instead of legacy UWP patterns.910---1112## Namespace Changes1314All `Windows.UI.Xaml.*` namespaces move to `Microsoft.UI.Xaml.*`:1516| UWP Namespace | WinUI 3 Namespace |17|--------------|-------------------|18| `Windows.UI.Xaml` | `Microsoft.UI.Xaml` |19| `Windows.UI.Xaml.Controls` | `Microsoft.UI.Xaml.Controls` |20| `Windows.UI.Xaml.Media` | `Microsoft.UI.Xaml.Media` |21| `Windows.UI.Xaml.Input` | `Microsoft.UI.Xaml.Input` |22| `Windows.UI.Xaml.Data` | `Microsoft.UI.Xaml.Data` |23| `Windows.UI.Xaml.Navigation` | `Microsoft.UI.Xaml.Navigation` |24| `Windows.UI.Xaml.Shapes` | `Microsoft.UI.Xaml.Shapes` |25| `Windows.UI.Composition` | `Microsoft.UI.Composition` |26| `Windows.UI.Input` | `Microsoft.UI.Input` |27| `Windows.UI.Colors` | `Microsoft.UI.Colors` |28| `Windows.UI.Text` | `Microsoft.UI.Text` |29| `Windows.UI.Core` | `Microsoft.UI.Dispatching` (for dispatcher) |3031---3233## Top 3 Most Common Copilot Mistakes3435### 1. ContentDialog Without XamlRoot3637```csharp38// ❌ WRONG — Throws InvalidOperationException in WinUI 339var dialog = new ContentDialog40{41 Title = "Error",42 Content = "Something went wrong.",43 CloseButtonText = "OK"44};45await dialog.ShowAsync();46```4748```csharp49// ✅ CORRECT — Set XamlRoot before showing50var dialog = new ContentDialog51{52 Title = "Error",53 Content = "Something went wrong.",54 CloseButtonText = "OK",55 XamlRoot = this.Content.XamlRoot // Required in WinUI 356};57await dialog.ShowAsync();58```5960### 2. MessageDialog Instead of ContentDialog6162```csharp63// ❌ WRONG — UWP API, not available in WinUI 3 desktop64var dialog = new Windows.UI.Popups.MessageDialog("Are you sure?", "Confirm");65await dialog.ShowAsync();66```6768```csharp69// ✅ CORRECT — Use ContentDialog70var dialog = new ContentDialog71{72 Title = "Confirm",73 Content = "Are you sure?",74 PrimaryButtonText = "Yes",75 CloseButtonText = "No",76 XamlRoot = this.Content.XamlRoot77};78var result = await dialog.ShowAsync();79if (result == ContentDialogResult.Primary)80{81 // User confirmed82}83```8485### 3. CoreDispatcher Instead of DispatcherQueue8687```csharp88// ❌ WRONG — CoreDispatcher does not exist in WinUI 389await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>90{91 StatusText.Text = "Done";92});93```9495```csharp96// ✅ CORRECT — Use DispatcherQueue97DispatcherQueue.TryEnqueue(() =>98{99 StatusText.Text = "Done";100});101102// With priority:103DispatcherQueue.TryEnqueue(DispatcherQueuePriority.High, () =>104{105 ProgressBar.Value = 100;106});107```108109---110111## Windowing Migration112113### Window Reference114115```csharp116// ❌ WRONG — Window.Current does not exist in WinUI 3117var currentWindow = Window.Current;118```119120```csharp121// ✅ CORRECT — Use a static property in App122public partial class App : Application123{124 public static Window MainWindow { get; private set; }125126 protected override void OnLaunched(LaunchActivatedEventArgs args)127 {128 MainWindow = new MainWindow();129 MainWindow.Activate();130 }131}132// Access anywhere: App.MainWindow133```134135### Window Management136137| UWP API | WinUI 3 API |138|---------|-------------|139| `ApplicationView.TryResizeView()` | `AppWindow.Resize()` |140| `AppWindow.TryCreateAsync()` | `AppWindow.Create()` |141| `AppWindow.TryShowAsync()` | `AppWindow.Show()` |142| `AppWindow.TryConsolidateAsync()` | `AppWindow.Destroy()` |143| `AppWindow.RequestMoveXxx()` | `AppWindow.Move()` |144| `AppWindow.GetPlacement()` | `AppWindow.Position` property |145| `AppWindow.RequestPresentation()` | `AppWindow.SetPresenter()` |146147### Title Bar148149| UWP API | WinUI 3 API |150|---------|-------------|151| `CoreApplicationViewTitleBar` | `AppWindowTitleBar` |152| `CoreApplicationView.TitleBar.ExtendViewIntoTitleBar` | `AppWindow.TitleBar.ExtendsContentIntoTitleBar` |153154---155156## Dialogs and Pickers Migration157158### File/Folder Pickers159160```csharp161// ❌ WRONG — UWP style, no window handle162var picker = new FileOpenPicker();163picker.FileTypeFilter.Add(".txt");164var file = await picker.PickSingleFileAsync();165```166167```csharp168// ✅ CORRECT — Initialize with window handle169var picker = new FileOpenPicker();170var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);171WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd);172picker.FileTypeFilter.Add(".txt");173var file = await picker.PickSingleFileAsync();174```175176## Threading Migration177178| UWP Pattern | WinUI 3 Equivalent |179|-------------|-------------------|180| `CoreDispatcher.RunAsync(priority, callback)` | `DispatcherQueue.TryEnqueue(priority, callback)` |181| `Dispatcher.HasThreadAccess` | `DispatcherQueue.HasThreadAccess` |182| `CoreDispatcher.ProcessEvents()` | No equivalent — restructure async code |183| `CoreWindow.GetForCurrentThread()` | Not available — use `DispatcherQueue.GetForCurrentThread()` |184185**Key difference**: UWP uses ASTA (Application STA) with built-in reentrancy blocking. WinUI 3 uses standard STA without this protection. Watch for reentrancy issues when async code pumps messages.186187---188189## Background Tasks Migration190191```csharp192// ❌ WRONG — UWP IBackgroundTask193public sealed class MyTask : IBackgroundTask194{195 public void Run(IBackgroundTaskInstance taskInstance) { }196}197```198199```csharp200// ✅ CORRECT — Windows App SDK AppLifecycle201using Microsoft.Windows.AppLifecycle;202203// Register for activation204var args = AppInstance.GetCurrent().GetActivatedEventArgs();205if (args.Kind == ExtendedActivationKind.AppNotification)206{207 // Handle background activation208}209```210211---212213## App Settings Migration214215| Scenario | Packaged App | Unpackaged App |216|----------|-------------|----------------|217| Simple settings | `ApplicationData.Current.LocalSettings` | JSON file in `LocalApplicationData` |218| Local file storage | `ApplicationData.Current.LocalFolder` | `Environment.GetFolderPath(SpecialFolder.LocalApplicationData)` |219220---221222## GetForCurrentView() Replacements223224All `GetForCurrentView()` patterns are unavailable in WinUI 3 desktop apps:225226| UWP API | WinUI 3 Replacement |227|---------|-------------------|228| `UIViewSettings.GetForCurrentView()` | Use `AppWindow` properties |229| `ApplicationView.GetForCurrentView()` | `AppWindow.GetFromWindowId(windowId)` |230| `DisplayInformation.GetForCurrentView()` | Win32 `GetDpiForWindow()` or `XamlRoot.RasterizationScale` |231| `CoreApplication.GetCurrentView()` | Not available — track windows manually |232| `SystemNavigationManager.GetForCurrentView()` | Handle back navigation in `NavigationView` directly |233234---235236## Testing Migration237238UWP unit test projects do not work with WinUI 3. You must migrate to the WinUI 3 test project templates.239240| UWP | WinUI 3 |241|-----|---------|242| Unit Test App (Universal Windows) | **Unit Test App (WinUI in Desktop)** |243| Standard MSTest project with UWP types | Must use WinUI test app for Xaml runtime |244| `[TestMethod]` for all tests | `[TestMethod]` for logic, `[UITestMethod]` for XAML/UI tests |245| Class Library (Universal Windows) | **Class Library (WinUI in Desktop)** |246247```csharp248// ✅ WinUI 3 unit test — use [UITestMethod] for any XAML interaction249[UITestMethod]250public void TestMyControl()251{252 var control = new MyLibrary.MyUserControl();253 Assert.AreEqual(expected, control.MyProperty);254}255```256257**Key:** The `[UITestMethod]` attribute tells the test runner to execute the test on the XAML UI thread, which is required for instantiating any `Microsoft.UI.Xaml` type.258259---260261## Migration Checklist2622631. [ ] Replace all `Windows.UI.Xaml.*` using directives with `Microsoft.UI.Xaml.*`2642. [ ] Replace `Windows.UI.Colors` with `Microsoft.UI.Colors`2653. [ ] Replace `CoreDispatcher.RunAsync` with `DispatcherQueue.TryEnqueue`2664. [ ] Replace `Window.Current` with `App.MainWindow` static property2675. [ ] Add `XamlRoot` to all `ContentDialog` instances2686. [ ] Initialize all pickers with `InitializeWithWindow.Initialize(picker, hwnd)`2697. [ ] Replace `MessageDialog` with `ContentDialog`2708. [ ] Replace `ApplicationView`/`CoreWindow` with `AppWindow`2719. [ ] Replace `CoreApplicationViewTitleBar` with `AppWindowTitleBar`27210. [ ] Replace all `GetForCurrentView()` calls with `AppWindow` equivalents27311. [ ] Update interop for Share and Print managers27412. [ ] Replace `IBackgroundTask` with `AppLifecycle` activation27513. [ ] Update project file: TFM to `net10.0-windows10.0.22621.0`, add `<UseWinUI>true</UseWinUI>`27614. [ ] Migrate unit tests to **Unit Test App (WinUI in Desktop)** project; use `[UITestMethod]` for XAML tests27715. [ ] Test both packaged and unpackaged configurations
Run npx skillmds@latest add github/winui3-migration-guide in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Maps legacy UWP APIs to correct Windows App SDK equivalents with before/after code snippets for migrating to WinUI 3. It is listed under Coding & Dev Tools, Refactoring on SkillMD.
SkillMD's automated safety review verdict for this skill is PASS. Independent scanners report: SkillSpector: PASS, Skill Scanner: PASS. Capability flags: docs only. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
GitHub (Microsoft) (@github) published this skill as a verified publisher. Their other Agent Skills are listed on their SkillMD profile.