Catalog
github/winui3-migration-guide

github

winui3-migration-guide

UWP-to-WinUI 3 migration reference. Maps legacy UWP APIs to correct Windows App SDK equivalents with before/after code snippets. Covers namespace changes, threading (CoreDispatcher to DispatcherQueue), windowing (CoreWindow to AppWindow), dialogs, pickers, sharing, printing, background tasks, and the most common Copilot code generation mistakes.

v1.0Latest
New~2.2kUpdated Jun 26, 2026

WinUI 3 Migration Guide

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";
});
// ✅ CORRECT — Use DispatcherQueue
DispatcherQueue.TryEnqueue(() =>
{
    StatusText.Text = "Done";
});

// With priority:
DispatcherQueue.TryEnqueue(DispatcherQueuePriority.High, () =>
{
    ProgressBar.Value = 100;
});

Windowing Migration

Window Reference

// ❌ WRONG — Window.Current does not exist in WinUI 3
var currentWindow = Window.Current;
// ✅ CORRECT — Use a static property in App
public partial class App : Application
{
    public static Window MainWindow { get; private set; }

    protected override void OnLaunched(LaunchActivatedEventArgs args)
    {
        MainWindow = new MainWindow();
        MainWindow.Activate();
    }
}
// Access anywhere: App.MainWindow

Window Management

UWP API WinUI 3 API
ApplicationView.TryResizeView() AppWindow.Resize()
AppWindow.TryCreateAsync() AppWindow.Create()
AppWindow.TryShowAsync() AppWindow.Show()
AppWindow.TryConsolidateAsync() AppWindow.Destroy()
AppWindow.RequestMoveXxx() AppWindow.Move()
AppWindow.GetPlacement() AppWindow.Position property
AppWindow.RequestPresentation() AppWindow.SetPresenter()

Title Bar

UWP API WinUI 3 API
CoreApplicationViewTitleBar AppWindowTitleBar
CoreApplicationView.TitleBar.ExtendViewIntoTitleBar AppWindow.TitleBar.ExtendsContentIntoTitleBar

Dialogs and Pickers Migration

File/Folder Pickers

// ❌ 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
}

App Settings Migration

Scenario Packaged App Unpackaged App
Simple settings ApplicationData.Current.LocalSettings JSON file in LocalApplicationData
Local file storage ApplicationData.Current.LocalFolder Environment.GetFolderPath(SpecialFolder.LocalApplicationData)

GetForCurrentView() Replacements

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

  1. Replace all Windows.UI.Xaml.* using directives with Microsoft.UI.Xaml.*
  2. Replace Windows.UI.Colors with Microsoft.UI.Colors
  3. Replace CoreDispatcher.RunAsync with DispatcherQueue.TryEnqueue
  4. Replace Window.Current with App.MainWindow static property
  5. Add XamlRoot to all ContentDialog instances
  6. Initialize all pickers with InitializeWithWindow.Initialize(picker, hwnd)
  7. Replace MessageDialog with ContentDialog
  8. Replace ApplicationView/CoreWindow with AppWindow
  9. Replace CoreApplicationViewTitleBar with AppWindowTitleBar
  10. Replace all GetForCurrentView() calls with AppWindow equivalents
  11. Update interop for Share and Print managers
  12. Replace IBackgroundTask with AppLifecycle activation
  13. Update project file: TFM to net10.0-windows10.0.22621.0, add <UseWinUI>true</UseWinUI>
  14. Migrate unit tests to Unit Test App (WinUI in Desktop) project; use [UITestMethod] for XAML tests
  15. Test both packaged and unpackaged configurations
Files1
1 files · 1.0 KB

Select a file to preview

Overall Score

88/100

Grade

A

Excellent

Safety

92

Quality

85

Clarity

90

Completeness

82

Summary

This skill provides a comprehensive UWP-to-WinUI 3 migration reference guide with before/after code snippets. It maps legacy UWP APIs to Windows App SDK equivalents, covering namespace changes, threading, windowing, dialogs, pickers, background tasks, and documents the most common Copilot-generated code mistakes (ContentDialog without XamlRoot, MessageDialog usage, CoreDispatcher vs. DispatcherQueue).

Detected Capabilities

code reference documentationAPI mapping referencebefore/after code example patternsmigration checklisterror diagnosis patterns

Trigger Keywords

Phrases that MCP clients use to match this skill to user intent.

migrate uwp to winui3winui3 api mappingfix copilot winui3 codewinui3 namespace changescontentdialog xamlroot errordispatcher migration winui3

Use Cases

  • Migrating an existing UWP desktop app to WinUI 3
  • Verifying that AI-generated WinUI 3 code uses correct modern APIs
  • Debugging WinUI 3 code that throws runtime errors like InvalidOperationException on dialogs
  • Updating test projects from UWP test framework to WinUI 3 test framework
  • Fixing namespace compatibility issues when porting UWP code to Windows App SDK

Quality Notes

  • Skill is well-structured with clear sections (Namespace Changes, Top 3 Mistakes, Windowing, Threading, etc.) that address the most common pain points in UWP migration
  • Excellent use of before/after code snippets with ❌ and ✅ markers to illustrate common mistakes versus correct patterns
  • Includes specific error types (InvalidOperationException) so developers can recognize when they've hit a known issue
  • Comprehensive migration checklist at the end provides actionable steps for methodical migration
  • Covers both packaged and unpackaged app scenarios for settings migration
  • Threading section explains the key architectural difference between UWP's ASTA and WinUI 3's STA to help developers understand reentrance risk
  • Testing migration section explicitly addresses the common error of trying to use UWP test projects with WinUI 3, with clear guidance to [UITestMethod]
  • Reference tables (Window Management, Threading, GetForCurrentView replacements) make API mapping quick to scan
  • Includes Win32 interop patterns (window handle initialization for pickers) which are often missed in generated code
Model: claude-haiku-4-5-20251001Analyzed: Jun 26, 2026

Reviews

Add this skill to your library to leave a review.

No reviews yet

Be the first to share your experience.

Use github/winui3-migration-guide in your dev environment

Command Palette

Search for a command to run...