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

Note: this form of XamlRoot works inside a Window class. Inside a page or user control, use the XamlRoot of that element or of the main window content from App.MainWindow.

2. MessageDialog Instead of ContentDialog

// ❌ AVOID — UWP API, needs window handle setup 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
}

MessageDialog can work in WinUI 3 desktop if it is initialized with the window handle, the same way as pickers, but ContentDialog is preferred.

3. CoreDispatcher Instead of DispatcherQueue

// ❌ WRONG — the Dispatcher property is null or unusable in WinUI 3 desktop
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

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 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 — for dispatcher access only, 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. Avoid blocking waits on async results on the UI thread, guard event handlers that can run again with a flag or semaphore, turn off the triggering UI while awaiting, and marshal state changes through DispatcherQueue.TryEnqueue.


Background Tasks Migration

// UWP IBackgroundTask — still usable in packaged apps when registered through supported background task APIs
public sealed class MyTask : IBackgroundTask
{
    public void Run(IBackgroundTaskInstance taskInstance) { }
}
// ✅ Windows App SDK AppLifecycle — activation handling only, not a replacement for trigger based background work
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 settings

ApplicationData.Current.LocalSettings

JSON file in LocalApplicationData

Local file storage

ApplicationData.Current.LocalFolder

Environment.GetFolderPath(SpecialFolder.LocalApplicationData)

Use the JSON file only for settings that are not sensitive; keep secrets and tokens in a protected Windows credential store.


GetForCurrentView() Replacements

Most GetForCurrentView() patterns depend on CoreWindow and are unsupported in WinUI 3 desktop apps; some have window based interop equivalents. Verify against current Microsoft Learn Windows App SDK documentation:

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

Replace expected in the sample with the value your test expects before running it.

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 GetForCurrentView() calls per the replacement table above
  11. Update interop for Share and Print managers — like pickers, these managers need the window handle through interop; this guide does not detail them
  12. Register background tasks again using supported background task APIs; use AppLifecycle only for activation handling
  13. Update project file: TFM to net10.0-windows10.0.22621.0, add <UseWinUI>true</UseWinUI>, reference the Windows App SDK package pinned to a tested stable version rather than a floating range, and match the target framework to the installed SDK
  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.cgr.dev/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.