Claude Agent Skill · by Github

Winui3 Migration Guide

The winui3-migration-guide skill provides a reference for developers migrating Universal Windows Platform (UWP) applications to WinUI 3 and the Windows App SDK,

Install
Terminal · npx
$npx skills add https://github.com/github/awesome-copilot --skill winui3-migration-guide
Works with Paperclip

How Winui3 Migration Guide fits into a Paperclip company.

Winui3 Migration Guide drops into any Paperclip agent that handles this kind of work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.

S
SaaS FactoryPaired

Pre-configured AI company — 18 agents, 18 skills, one-time purchase.

$27$59
Explore pack
Source file
SKILL.md277 lines
Expand
---name: winui3-migration-guidedescription: '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.'--- # 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 ```csharp// ❌ WRONG — Throws InvalidOperationException in WinUI 3var dialog = new ContentDialog{    Title = "Error",    Content = "Something went wrong.",    CloseButtonText = "OK"};await dialog.ShowAsync();``` ```csharp// ✅ CORRECT — Set XamlRoot before showingvar 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 ```csharp// ❌ WRONG — UWP API, not available in WinUI 3 desktopvar dialog = new Windows.UI.Popups.MessageDialog("Are you sure?", "Confirm");await dialog.ShowAsync();``` ```csharp// ✅ CORRECT — Use ContentDialogvar 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 ```csharp// ❌ WRONG — CoreDispatcher does not exist in WinUI 3await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>{    StatusText.Text = "Done";});``` ```csharp// ✅ CORRECT — Use DispatcherQueueDispatcherQueue.TryEnqueue(() =>{    StatusText.Text = "Done";}); // With priority:DispatcherQueue.TryEnqueue(DispatcherQueuePriority.High, () =>{    ProgressBar.Value = 100;});``` --- ## Windowing Migration ### Window Reference ```csharp// ❌ WRONG — Window.Current does not exist in WinUI 3var currentWindow = Window.Current;``` ```csharp// ✅ CORRECT — Use a static property in Apppublic 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 ```csharp// ❌ WRONG — UWP style, no window handlevar picker = new FileOpenPicker();picker.FileTypeFilter.Add(".txt");var file = await picker.PickSingleFileAsync();``` ```csharp// ✅ CORRECT — Initialize with window handlevar 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 ```csharp// ❌ WRONG — UWP IBackgroundTaskpublic sealed class MyTask : IBackgroundTask{    public void Run(IBackgroundTaskInstance taskInstance) { }}``` ```csharp// ✅ CORRECT — Windows App SDK AppLifecycleusing Microsoft.Windows.AppLifecycle; // Register for activationvar 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)** | ```csharp// ✅ 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 property5. [ ] Add `XamlRoot` to all `ContentDialog` instances6. [ ] 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` equivalents11. [ ] Update interop for Share and Print managers12. [ ] Replace `IBackgroundTask` with `AppLifecycle` activation13. [ ] 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 tests15. [ ] Test both packaged and unpackaged configurations