56 results available
Sign in
Skills directory

winui3-migration-guide

github

·

Last changed
Hardened

This skill has been hardened by Chainguard

Last changed

This version passed the hardening gate. Hardening applied 12 targeted changes and preserved all other text. Classified findings before hardening: 0. Classified findings closed: 0. Classified findings remaining: 0. Unclassified scanner findings remaining: 0. Review findings closed: 12. Review findings remaining: 1.


Open before hardening

None

Open after hardening

None


Expand
File
Group
Subtype
Severity
Status

No findings available

0 findings


SKILL.md

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.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();

This form applies inside a Window. Inside a Page or UserControl, use the XamlRoot of that element instead.

2. MessageDialog Instead of ContentDialog

// ❌ WRONG — UWP API, needs window handle setup in WinUI 3 desktop, prefer ContentDialog
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 — Dispatcher returns null for WinUI 3 windows, use DispatcherQueue
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;
});

The enqueue call returns false when the work could not be queued, for example while the queue is shutting down. Check the result and log or handle that case.


Windowing Migration

Window Reference

// ❌ WRONG — Window.Current returns null in WinUI 3 desktop apps
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

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();

Share and Print

Like pickers, the Share and Print managers in desktop apps must be obtained for a specific window using its window handle through their interop interfaces. Follow the official Microsoft documentation for this interop code rather than writing it from memory.

Threading Migration

UWP PatternWinUI 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 notification activation
}

This sample covers notification activation only. It is not a full replacement for timer, push or maintenance background work. Check the official Microsoft documentation for the supported background task path before migrating those triggers.


App Settings Migration

ScenarioPackaged AppUnpackaged App

Simple settings

ApplicationData.Current.LocalSettings

JSON file in LocalApplicationData

Local file storage

ApplicationData.Current.LocalFolder

Environment.GetFolderPath(SpecialFolder.LocalApplicationData)

The JSON settings file is plain text. Keep it to settings that are not sensitive, store secrets such as passwords or tokens in the Windows credential store or with data protection, and place the file in a folder for your app.


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 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);
}

Declare expected with the known value of the property before the assertion.

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. Review each IBackgroundTask trigger and use AppLifecycle activation only for notification activation
  13. Update project file: TFM to net10.0-windows10.0.22621.0, add <UseWinUI>true</UseWinUI> (the TFM shown is an example, so match it to your installed SDKs), and reference the Windows App SDK package from the official NuGet feed with an explicit pinned version and a lock file
  14. Migrate unit tests to Unit Test App (WinUI in Desktop) project; use [UITestMethod] for XAML tests
  15. Test both packaged and unpackaged configurations

Install

Install with chainctl
chainctl skill install public/github/winui3-migration-guide:latest
Get started with chainctl
View source

Harden your own skills

Bring Chainguard's hardening pipeline to your first-party skills — custom rulesets, automated remediation, full audit trail.

Provenance

Upstream sourcehttps://github.com/github/awesome-copilot
Upstream commitdcc2ee10865be640ef3ef2d3abed57336ad7564a
OCI reference

skills.chainreg.biz/public/github.com/github/skills/winui3-migration-guide:latest

License

MIT

Files

HARDENING.md

LICENSE

SKILL.md


The trusted source for open source

Talk to an expert
PrivacyTerms

Product

Chainguard ContainersChainguard LibrariesChainguard VMsChainguard OS PackagesChainguard ActionsChainguard Agent SkillsIntegrationsPricing
© 2026 Chainguard, Inc. All Rights Reserved.
Chainguard® and the Chainguard logo are registered trademarks of Chainguard, Inc. in the United States and/or other countries.
The other respective trademarks mentioned on this page are owned by the respective companies and use of them does not imply any affiliation or endorsement.