🚀 快速安装
复制以下命令并运行,立即安装此 Skill:
npx skills add https://github.com/github/awesome-copilot --skill winui3-migration-guide
💡 提示:需要 Node.js 和 NPM
WinUI 3 迁移指南
在将 UWP 应用迁移到 WinUI 3 / Windows 应用 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 (用于调度器) |
Copilot 最常见的 3 个错误
1. 未设置 XamlRoot 的 ContentDialog
// ❌ 错误 — 在 WinUI 3 中会引发 InvalidOperationException
var dialog = new ContentDialog
{
Title = "错误",
Content = "发生错误。",
CloseButtonText = "确定"
};
await dialog.ShowAsync();
// ✅ 正确 — 显示前设置 XamlRoot
var dialog = new ContentDialog
{
Title = "错误",
Content = "发生错误。",
CloseButtonText = "确定",
XamlRoot = this.Content.XamlRoot // 在 WinUI 3 中是必需的
};
await dialog.ShowAsync();
2. 使用 MessageDialog 而非 ContentDialog
// ❌ 错误 — UWP API,在 WinUI 3 桌面应用中不可用
var dialog = new Windows.UI.Popups.MessageDialog("确定吗?", "确认");
await dialog.ShowAsync();
// ✅ 正确 — 使用 ContentDialog
var dialog = new ContentDialog
{
Title = "确认",
Content = "确定吗?",
PrimaryButtonText = "是",
CloseButtonText = "否",
XamlRoot = this.Content.XamlRoot
};
var result = await dialog.ShowAsync();
if (result == ContentDialogResult.Primary)
{
// 用户确认
}
3. 使用 CoreDispatcher 而非 DispatcherQueue
// ❌ 错误 — CoreDispatcher 在 WinUI 3 中不存在
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
StatusText.Text = "完成";
});
// ✅ 正确 — 使用 DispatcherQueue
DispatcherQueue.TryEnqueue(() =>
{
StatusText.Text = "完成";
});
// 带优先级:
DispatcherQueue.TryEnqueue(DispatcherQueuePriority.High, () =>
{
ProgressBar.Value = 100;
});
窗口迁移
窗口引用
// ❌ 错误 — Window.Current 在 WinUI 3 中不存在
var currentWindow = Window.Current;
// ✅ 正确 — 在 App 中使用静态属性
public partial class App : Application
{
public static Window MainWindow { get; private set; }
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
MainWindow = new MainWindow();
MainWindow.Activate();
}
}
// 任意位置访问: 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 |
对话框和选择器迁移
文件/文件夹选择器
// ❌ 错误 — UWP 样式,无窗口句柄
var picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".txt");
var file = await picker.PickSingleFileAsync();
// ✅ 正确 — 使用窗口句柄初始化
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(应用程序 STA)。WinUI 3 使用没有此保护的标准 STA。当异步代码处理消息时,请注意重入问题。
后台任务迁移
// ❌ 错误 — UWP IBackgroundTask
public sealed class MyTask : IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance) { }
}
// ✅ 正确 — Windows 应用 SDK AppLifecycle
using Microsoft.Windows.AppLifecycle;
// 注册激活
var args = AppInstance.GetCurrent().GetActivatedEventArgs();
if (args.Kind == ExtendedActivationKind.AppNotification)
{
// 处理后台激活
}
应用设置迁移
| 场景 | 打包应用 | 未打包应用 |
|---|---|---|
| 简单设置 | ApplicationData.Current.LocalSettings |
LocalApplicationData 中的 JSON 文件 |
| 本地文件存储 | ApplicationData.Current.LocalFolder |
Environment.GetFolderPath(SpecialFolder.LocalApplicationData) |
GetForCurrentView() 的替代方案
所有 GetForCurrentView() 模式在 WinUI 3 桌面应用中均不可用:
| 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 单元测试 — 任何 XAML 交互使用 [UITestMethod]
[UITestMethod]
public void TestMyControl()
{
var control = new MyLibrary.MyUserControl();
Assert.AreEqual(预期值, 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等效项 - 更新共享和打印管理器的互操作
- 将
IBackgroundTask替换为AppLifecycle激活 - 更新项目文件:TFM 为
net10.0-windows10.0.22621.0,添加<UseWinUI>true</UseWinUI> - 将单元测试迁移到 单元测试应用(桌面版 WinUI) 项目;XAML 测试使用
[UITestMethod] - 测试打包和未打包两种配置
📄 原始文档
完整文档(英文):
https://skills.sh/github/awesome-copilot/winui3-migration-guide
💡 提示:点击上方链接查看 skills.sh 原始英文文档,方便对照翻译。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

评论(0)