关于 winui3-migration-guide
winui3-migration-guide 是帮助开发者将 UWP 应用迁移到 WinUI 3,或检查生成代码是否使用新 API 的技能。它提供映射、常见问题修正和涵盖界面、窗口、线程及测试的清单。
主要功能
- 01将 UWP 命名空间和 API 映射到 WinUI 3
- 02修正常见对话框和调度器用法
- 03更新窗口、选择器和线程代码
- 04指导后台任务与设置迁移
- 05提供项目和测试变更清单
适用场景
- 01将 UWP 应用迁移到 WinUI 3
- 02检查生成代码中的旧版 UWP API
- 03替换窗口和文件选择器用法
- 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.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(用于 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 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 属性 |
AppWindow.RequestPresentation() | AppWindow.SetPresenter() |
标题栏
| UWP API | WinUI 3 API |
|---|---|
CoreApplicationViewTitleBar | AppWindowTitleBar |
CoreApplicationView.TitleBar.ExtendViewIntoTitleBar | AppWindow.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.HasThreadAccess | DispatcherQueue.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.LocalSettings | LocalApplicationData 中的 JSON 文件 |
| 本地文件存储 | ApplicationData.Current.LocalFolder | Environment.GetFolderPath(SpecialFolder.LocalApplicationData) |
GetForCurrentView() 替代方案
在 WinUI 3 桌面应用中,所有 GetForCurrentView() 模式均不可用:
| UWP API | WinUI 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 测试项目模板。
| UWP | WinUI 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 类型所必需的。
迁移清单
- 将所有
Windows.UI.Xaml.*using 指令替换为Microsoft.UI.Xaml.* - 将
Windows.UI.Colors替换为Microsoft.UI.Colors - 将
CoreDispatcher.RunAsync替换为DispatcherQueue.TryEnqueue - 将
Window.Current替换为App.MainWindow静态属性 - 为所有
ContentDialog实例添加XamlRoot - 使用
InitializeWithWindow.Initialize(picker, hwnd)初始化所有选取器 - 将
MessageDialog替换为ContentDialog - 将
ApplicationView/CoreWindow替换为AppWindow - 将
CoreApplicationViewTitleBar替换为AppWindowTitleBar - 将所有
GetForCurrentView()调用替换为AppWindow等效项 - 更新 Share 和 Print 管理器的互操作
- 将
IBackgroundTask替换为AppLifecycle激活 - 更新项目文件:将 TFM 改为
net10.0-windows10.0.22621.0,添加<UseWinUI>true</UseWinUI> - 将单元测试迁移到 单元测试应用(桌面版 WinUI) 项目;对 XAML 测试使用
[UITestMethod] - 测试打包和非打包两种配置
评论
支持 Markdown