Generated banner for Winui3 Migration Guide
Generated logo for Winui3 Migration Guide

Winui3 Migration Guide

GitHubOfficialFirst committed by niels9001Distributed by GitHub

  • Skill
  • Guidelines
  • Software development
  • MIT
  • No issues found

From the author

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.
— the description by niels9001

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

The WinUI 3 Migration Guide provides developers with a structured approach to transitioning UWP applications to the Windows App SDK. It details critical API changes, namespace updates, and architectural shifts required for modernizing desktop applications. The guide covers essential areas including threading, windowing, dialog management, and background tasks, while highlighting common pitfalls encountered during the migration process.

What it does

  • Maps legacy Windows.UI.Xaml namespaces to Microsoft.UI.Xaml equivalents.
  • Provides code patterns for replacing deprecated UWP APIs with WinUI 3 alternatives.
  • Explains the transition from CoreDispatcher to DispatcherQueue for thread management.
  • Details the initialization of pickers and dialogs using window handles.
  • Outlines the migration path for background tasks and app lifecycle management.
  • Provides a checklist for updating project configurations and test suites.

When to use it

  • When porting an existing UWP application to WinUI 3.
  • When debugging runtime errors caused by using legacy UWP patterns in a WinUI 3 environment.
  • When verifying that AI-generated code adheres to WinUI 3 API standards.
  • When setting up unit testing for WinUI 3 desktop applications.

Advantages

  • Reduces migration friction by providing direct before-and-after code comparisons.
  • Addresses common errors such as missing XamlRoot or incorrect dispatcher usage.
  • Centralizes complex interop requirements for window management and file pickers.
  • Provides a clear roadmap for updating project files and test infrastructure.

Usage examples

“How do I show a ContentDialog in WinUI 3?”
The guide explains that you must set the XamlRoot property on the ContentDialog instance to the current window's content root before calling ShowAsync.
“What is the WinUI 3 replacement for CoreDispatcher?”
The guide instructs to use DispatcherQueue.TryEnqueue, providing examples for both standard and priority-based execution.
“How do I initialize a FileOpenPicker in WinUI 3?”
The guide provides the pattern for using WinRT.Interop.InitializeWithWindow to associate the picker with the application's window handle.
“Why is my unit test failing in WinUI 3?”
The guide explains the need to use the WinUI 3 test project template and the [UITestMethod] attribute for tests interacting with XAML elements.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/github/winui3-migration-guide/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip winui3-migration-guide.zip -d .agents/skills

Documentation by niels9001

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 NamespaceWinUI 3 Namespace
Windows.UI.XamlMicrosoft.UI.Xaml
Windows.UI.Xaml.ControlsMicrosoft.UI.Xaml.Controls
Windows.UI.Xaml.MediaMicrosoft.UI.Xaml.Media
Windows.UI.Xaml.InputMicrosoft.UI.Xaml.Input
Windows.UI.Xaml.DataMicrosoft.UI.Xaml.Data
Windows.UI.Xaml.NavigationMicrosoft.UI.Xaml.Navigation
Windows.UI.Xaml.ShapesMicrosoft.UI.Xaml.Shapes
Windows.UI.CompositionMicrosoft.UI.Composition
Windows.UI.InputMicrosoft.UI.Input
Windows.UI.ColorsMicrosoft.UI.Colors
Windows.UI.TextMicrosoft.UI.Text
Windows.UI.CoreMicrosoft.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 APIWinUI 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 APIWinUI 3 API
CoreApplicationViewTitleBarAppWindowTitleBar
CoreApplicationView.TitleBar.ExtendViewIntoTitleBarAppWindow.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 PatternWinUI 3 Equivalent
CoreDispatcher.RunAsync(priority, callback)DispatcherQueue.TryEnqueue(priority, callback)
Dispatcher.HasThreadAccessDispatcherQueue.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

ScenarioPackaged AppUnpackaged App
Simple settingsApplicationData.Current.LocalSettingsJSON file in LocalApplicationData
Local file storageApplicationData.Current.LocalFolderEnvironment.GetFolderPath(SpecialFolder.LocalApplicationData)

GetForCurrentView() Replacements

All GetForCurrentView() patterns are unavailable in WinUI 3 desktop apps:

UWP APIWinUI 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.

UWPWinUI 3
Unit Test App (Universal Windows)Unit Test App (WinUI in Desktop)
Standard MSTest project with UWP typesMust 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

Files

Requirements and compatibility

Written for: GitHub Copilot

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

First committed by
GitHub avatar of niels9001niels9001
Publisher
GitHub (Official)
Distributed by
GitHub
Source
github/awesome-copilot · skills/winui3-migration-guide · commit 797337f
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced
Contributors
niels9001

AutoGineer is not affiliated with or endorsed by niels9001 or GitHub.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download winui3-migration-guide.zip