mcpField
W
winui3-migration-guide

winui3-migration-guide

github.com/github开发40.5k5.7k 次安装今天更新
代码仓库

关于 winui3-migration-guide

winui3-migration-guide 是帮助开发者将 UWP 应用迁移到 WinUI 3,或检查生成代码是否使用新 API 的技能。它提供映射、常见问题修正和涵盖界面、窗口、线程及测试的清单。

主要功能

  1. 01将 UWP 命名空间和 API 映射到 WinUI 3
  2. 02修正常见对话框和调度器用法
  3. 03更新窗口、选择器和线程代码
  4. 04指导后台任务与设置迁移
  5. 05提供项目和测试变更清单

适用场景

  1. 01将 UWP 应用迁移到 WinUI 3
  2. 02检查生成代码中的旧版 UWP API
  3. 03替换窗口和文件选择器用法
  4. 04更新 WinUI 3 测试

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/github/awesome-copilot --skill winui3-migration-guide

安装后在 Claude Code 中输入/winui3-migration-guide确认已加载。

详细介绍

WinUI 3 迁移指南

当你将 UWP 应用迁移到 WinUI 3 / Windows App SDK,或需要验证生成的代码使用的是正确的 WinUI 3 API,而非旧式 UWP 模式时,请使用此技能。


命名空间变更

所有 Windows.UI.Xaml.* 命名空间都迁移到 Microsoft.UI.Xaml.*:

UWP 命名空间WinUI 3 命名空间
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(用于 dispatcher)

Copilot 最常见的 3 个错误

1. 缺少 XamlRoot 的 ContentDialog
// ❌ 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 而非 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 而非 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;
});

窗口管理迁移

Window 引用
// ❌ 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
窗口管理
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 属性
AppWindow.RequestPresentation()AppWindow.SetPresenter()
标题栏
UWP APIWinUI 3 API
CoreApplicationViewTitleBarAppWindowTitleBar
CoreApplicationView.TitleBar.ExtendViewIntoTitleBarAppWindow.TitleBar.ExtendsContentIntoTitleBar

对话框和选取器迁移

文件/文件夹选取器
// ❌ 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();

线程迁移

UWP 模式WinUI 3 等效方案
CoreDispatcher.RunAsync(priority, callback)DispatcherQueue.TryEnqueue(priority, callback)
Dispatcher.HasThreadAccessDispatcherQueue.HasThreadAccess
CoreDispatcher.ProcessEvents()无等效方案——重构异步代码
CoreWindow.GetForCurrentThread()不可用——使用 DispatcherQueue.GetForCurrentThread()

关键区别:UWP 使用 ASTA(Application STA),内置重入阻止机制。WinUI 3 使用标准 STA,没有此保护。当异步代码泵送消息时,请注意重入问题。


后台任务迁移

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

应用设置迁移

场景打包应用未打包应用
简单设置ApplicationData.Current.LocalSettingsLocalApplicationData 中的 JSON 文件
本地文件存储ApplicationData.Current.LocalFolderEnvironment.GetFolderPath(SpecialFolder.LocalApplicationData)

GetForCurrentView() 替代方案

在 WinUI 3 桌面应用中,所有 GetForCurrentView() 模式均不可用:

UWP APIWinUI 3 替代方案
UIViewSettings.GetForCurrentView()使用 AppWindow 属性
ApplicationView.GetForCurrentView()AppWindow.GetFromWindowId(windowId)
DisplayInformation.GetForCurrentView()Win32 GetDpiForWindow() 或 XamlRoot.RasterizationScale
CoreApplication.GetCurrentView()不可用——手动跟踪窗口
SystemNavigationManager.GetForCurrentView()直接在 NavigationView 中处理返回导航

测试迁移

UWP 单元测试项目无法与 WinUI 3 配合使用。你必须迁移到 WinUI 3 测试项目模板。

UWPWinUI 3
单元测试应用(通用 Windows)单元测试应用(桌面版 WinUI)
使用 UWP 类型的标准 MSTest 项目必须使用 WinUI 测试应用以支持 Xaml 运行时
所有测试使用 [TestMethod]逻辑测试使用 [TestMethod],XAML/UI 测试使用 [UITestMethod]
类库(通用 Windows)类库(桌面版 WinUI)
// ✅ WinUI 3 unit test — use [UITestMethod] for any XAML interaction
[UITestMethod]
public void TestMyControl()
{
    var control = new MyLibrary.MyUserControl();
    Assert.AreEqual(expected, control.MyProperty);
}

关键: [UITestMethod] 特性告知测试运行器在 XAML UI 线程上执行测试,这是实例化任何 Microsoft.UI.Xaml 类型所必需的。


迁移清单

  1. 将所有 Windows.UI.Xaml.* using 指令替换为 Microsoft.UI.Xaml.*
  2. 将 Windows.UI.Colors 替换为 Microsoft.UI.Colors
  3. 将 CoreDispatcher.RunAsync 替换为 DispatcherQueue.TryEnqueue
  4. 将 Window.Current 替换为 App.MainWindow 静态属性
  5. 为所有 ContentDialog 实例添加 XamlRoot
  6. 使用 InitializeWithWindow.Initialize(picker, hwnd) 初始化所有选取器
  7. 将 MessageDialog 替换为 ContentDialog
  8. 将 ApplicationView/CoreWindow 替换为 AppWindow
  9. 将 CoreApplicationViewTitleBar 替换为 AppWindowTitleBar
  10. 将所有 GetForCurrentView() 调用替换为 AppWindow 等效项
  11. 更新 Share 和 Print 管理器的互操作
  12. 将 IBackgroundTask 替换为 AppLifecycle 激活
  13. 更新项目文件:将 TFM 改为 net10.0-windows10.0.22621.0,添加 <UseWinUI>true</UseWinUI>
  14. 将单元测试迁移到 单元测试应用(桌面版 WinUI) 项目;对 XAML 测试使用 [UITestMethod]
  15. 测试打包和非打包两种配置

评论

支持 Markdown