dotnet-wpf-migration dotnet-wpf-migration

这个技能提供Windows桌面应用程序从.NET Framework迁移到现代框架的详细指南,包括WPF、WinForms、UWP到.NET 8+、WinUI 3和Uno Platform的路径、决策矩阵、工具使用和步骤说明。关键词:.NET迁移、WPF、WinUI、Uno Platform、桌面应用现代化、dotnet-upgrade-assistant、Windows开发。

前端开发 0 次安装 0 次浏览 更新于 3/6/2026

名称: dotnet-wpf-migration 描述: “迁移桌面应用程序。WPF/WinForms 到 .NET 8+,WPF 到 WinUI 或 Uno,UWP 到 WinUI。” 用户可调用: false

dotnet-wpf-migration

基于上下文依赖的 Windows 桌面应用程序迁移指南。覆盖 WPF .NET Framework 到 .NET 8+、WPF 到 WinUI 3(仅限 Windows 现代化)、WPF 到 Uno Platform(跨平台)、WinForms .NET Framework 到 .NET 8+、UWP 到 WinUI 3、UWP 到 Uno Platform(交叉参考),以及基于项目约束选择正确迁移目标的决策矩阵。

版本假设: .NET 8.0+ 基线(当前 LTS)。dotnet-upgrade-assistant 用于自动化迁移。 .NET 9 功能在适用时明确标记。

范围

  • 迁移决策矩阵(当前框架到目标框架)
  • WPF .NET Framework 到 .NET 8+ 迁移
  • WPF 到 WinUI 3(仅限 Windows 现代化)
  • WPF 到 Uno Platform(跨平台)
  • WinForms .NET Framework 到 .NET 8+
  • UWP 到 WinUI 3 和 UWP 到 Uno Platform

超出范围

  • WPF .NET 8+ 开发模式 – 见 [技能:dotnet-wpf-modern]
  • WinUI 3 开发模式 – 见 [技能:dotnet-winui]
  • WinForms .NET 8+ 开发模式 – 见 [技能:dotnet-winforms-basics]
  • Uno Platform 开发模式 – 见 [技能:dotnet-uno-platform]
  • 框架选择决策树 – 见 [技能:dotnet-ui-chooser]
  • 桌面测试 – 见 [技能:dotnet-ui-testing-core]

交叉参考: [技能:dotnet-wpf-modern] 用于 WPF .NET 8+ 模式,[技能:dotnet-winui] 用于 WinUI 3 模式,[技能:dotnet-winforms-basics] 用于 WinForms .NET 8+ 模式,[技能:dotnet-uno-platform] 用于 Uno Platform 模式,[技能:dotnet-ui-chooser] 用于框架选择,[技能:dotnet-ui-testing-core] 用于桌面测试。


迁移路径概览

根据当前框架和目标目标选择迁移路径。每条路径在努力、风险和能力增益方面有不同的权衡。

当前 目标 努力 风险 何时选择
WPF .NET Framework WPF .NET 8+ 低-中等 现代化运行时,保留现有 UI
WPF .NET Framework WinUI 3 中等 现代 Windows UI,触摸/笔,Fluent
WPF .NET Framework Uno Platform 中等-高 需要跨平台
WinForms .NET Framework WinForms .NET 8+ 现代化运行时,保留现有 UI
UWP WinUI 3 中等 中等 保持仅限 Windows,现代运行时
UWP Uno Platform 中等-高 中等 从 UWP 需要跨平台

WPF .NET Framework 到 .NET 8+

最低风险的迁移路径。保持现有 XAML 和代码隐藏完整,同时迁移到现代 .NET,具有更好的性能、DI 支持和并行部署。

使用 dotnet-upgrade-assistant

.NET 升级助手自动化大部分迁移:

# 安装升级助手
dotnet tool install -g upgrade-assistant

# 首先分析项目(非破坏性)
upgrade-assistant analyze MyWpfApp.sln

# 升级项目
upgrade-assistant upgrade MyWpfApp.sln

升级助手处理的内容:

  • 从旧格式转换 .csproj 为 SDK 风格
  • packages.configPackageReference 迁移
  • TFM 更改为 net8.0-windows
  • AssemblyInfo.cs 属性移动到 .csproj
  • 常见 API 替换和命名空间更新

需要手动工作的内容:

  • App.config 设置迁移到 appsettings.json 或 Host 构建器配置
  • Settings.settings / My.Settings (VB.NET) 迁移
  • 第三方控件库更新(检查供应商 .NET 8 兼容性)
  • WCF 客户端引用(使用 CoreWCF 或迁移到 gRPC/REST)
  • COM 互操作调整(System.Runtime.InteropServices 中的语法差异)
  • 自定义 MSBuild 目标和构建脚本

API 兼容性

大多数 WPF API 在 .NET Framework 和 .NET 8+ 之间是相同的。关键差异:

区域 .NET Framework .NET 8+ 操作
剪贴板 Clipboard.SetText() 相同 API 无更改
打印 PrintDialog, PrintVisual 相同 API 无更改
BitmapEffect 已弃用(软件渲染) 已移除 使用 Effect / ShaderEffect
DrawingContext.PushEffect 可用 已移除 使用 ShaderEffect
XPS 文档 System.Windows.Xps 需要 NuGet 包 添加 System.Windows.Xps PackageReference
语音合成 System.Speech 需要 NuGet 包 添加 System.Speech PackageReference

NuGet 包更新

迁移后,更新 NuGet 包到 .NET 8 兼容版本:

# 列出过时包
dotnet list package --outdated

# 更新包(一次一个以安全迁移)
dotnet add package Newtonsoft.Json --version 13.*
dotnet add package MaterialDesignThemes --version 5.*

常见包替换:

  • Unity 容器 -> Microsoft.Extensions.DependencyInjection(内置)
  • Autofac -> 更新到最新(支持 .NET 8)
  • log4net / NLog -> 考虑 Microsoft.Extensions.Logging 与 Serilog 或 NLog 提供程序
  • EntityFramework (EF6) -> Microsoft.EntityFrameworkCore 8.x

破坏性更改清单

  • 默认高 DPI 行为已更改。 .NET 8 WPF 默认启用 PerMonitorV2 DPI 感知(不像 .NET Framework 的 SystemAware)。
  • 可空引用类型。 新项目启用 NRT。现有代码可能产生警告。最初用 <Nullable>disable</Nullable> 抑制,然后逐步修复。
  • 隐式 using。 新 SDK 风格项目启用隐式 using。可能与现有 using 语句冲突。如果需要,用 <ImplicitUsings>disable</ImplicitUsings> 禁用。
  • 程序集加载。 AssemblyLoadContext 替换 AppDomain 用于程序集隔离。使用 AppDomain.CreateDomain 的插件架构需要重做。
  • 运行时行为。 .NET 8 GC 对 Gen0/Gen1 收集更激进。依赖终结器的代码可能表现不同。

有关迁移后的 WPF 模式(Host 构建器、MVVM 工具包、现代 C#),请参阅 [技能:dotnet-wpf-modern]。


WPF 到 WinUI 3

当需要现代 Windows 原生 UI 时迁移:Fluent Design、触摸/笔输入、Windows 11 集成(小部件、Mica),或现代 .NET 上的 UWP 风格 API。这是一个部分重写 – XAML 概念转移,但 API 和命名空间不同。

何时此路径有意义

  • 应用程序仅限 Windows 并将保持仅限 Windows
  • 需要现代Fluent Design 控件、触摸/笔支持或 Windows 11 功能
  • 团队愿意投资XAML 重写努力
  • 应用程序正在积极开发,有持续功能工作(证明投资合理)

何时考虑替代方案

  • 如果需要跨平台 -> 迁移到 Uno Platform 代替(WinUI XAML 表面)
  • 如果应用程序处于维护模式 -> 迁移到 WPF .NET 8+ 代替(较低努力)
  • 如果 WPF Fluent 主题(.NET 9+)足够 -> 停留在 WPF .NET 8+ 与 ThemeMode = ThemeMode.System

XAML 差异

WPF XAML WinUI 3 XAML 备注
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 相同 URI(但解析为 Microsoft.UI.Xaml 类型,不是 System.Windows 无 xmlns 更改,但运行时类型不同
{Binding Path=Name} {x:Bind Name, Mode=OneWay} 优先使用 x:Bind(编译时、类型安全)
DataContext 绑定 代码隐藏属性 + x:Bind x:Bind 解析针对代码隐藏
Window 继承自 System.Windows.Window Window 继承自 Microsoft.UI.Xaml.Window 不同的基类和 API
UserControl UserControl(Microsoft.UI.Xaml 命名空间) 相同概念,不同命名空间
StyleTargetType 相同 工作方式相同
DataTemplate 需要 x:DataType 用于 x:Bind 编译绑定所需
ContextMenu MenuFlyout 不同的控件类型
StatusBar 无内置等效 使用自定义 CommandBarInfoBar
RibbonControl 无内置等效 使用 NavigationView + CommandBar

迁移策略

  1. 创建新的 WinUI 3 项目 与现有 WPF 项目并行
  2. 首先迁移共享逻辑 – 模型、服务、视图模型(如果使用 MVVM 工具包,它们在两者中都有效)
  3. 增量迁移视图 – 从简单页面开始,然后复杂页面
  4. 替换 WPF 特定控件 为 WinUI 等效(见上表)
  5. 更新数据绑定{Binding}{x:Bind} 以获取编译时安全
  6. 测试 Windows 集成 功能(通知、生命周期、文件关联)
  7. 选择部署模型 – MSIX(应用身份)或未打包(xcopy)

有关 WinUI 3 模式和项目设置,请参阅 [技能:dotnet-winui]。


WPF 到 Uno Platform

当需要从 WPF 代码库获得跨平台覆盖时迁移。Uno Platform 使用 WinUI XAML API 表面,因此 WPF XAML 技能部分转移,但迁移涉及适应 WinUI XAML 模式。

何时此路径有意义

  • 应用程序需要运行在多个平台(Windows、macOS、Linux、Web、移动)
  • 团队有WPF/XAML 专长,可转移到 WinUI XAML 表面
  • 愿意投资跨平台适应(平台特定行为、响应式布局)

何时考虑替代方案

  • 如果仅限 Windows -> 迁移到 WinUI 3(更简单,无跨平台开销)
  • 如果应用程序处于维护模式 -> 迁移到 WPF .NET 8+(最低努力)
  • 如果团队有Web 技能 -> 考虑 Blazor 用于 Web 交付

迁移方法

从 WPF 到 Uno Platform 的迁移类似于 WPF 到 WinUI 3(因为 Uno 使用 WinUI API 表面),但带有额外的跨平台考虑:

  1. 创建 Uno Platform 项目 与所需目标平台
  2. 迁移视图模型和服务 – 这些是平台独立的
  3. 适应 XAML 到 WinUI 语法(与 WPF 到 WinUI 迁移相同更改)
  4. 处理平台特定功能 使用条件编译或 Uno 平台扩展
  5. 替换仅限 Windows API 为跨平台替代(文件对话框、通知等)
  6. 测试每个目标平台 – 渲染和行为可能在 Skia 和原生目标之间不同

Uno 扩展用于常见模式

Uno 扩展提供常见 WPF 模式的跨平台替换:

WPF 模式 Uno 扩展替换
自定义导航 Uno.Extensions.Navigation
手动 DI 设置 Uno.Extensions.DependencyInjection(包装 MS DI)
appsettings.json 配置 Uno.Extensions.Configuration
手动 HTTP 客户端 Uno.Extensions.Http(带 Refit 的键入客户端)
手动序列化 Uno.Extensions.Serialization

有关 Uno Platform 开发模式,请参阅 [技能:dotnet-uno-platform]。有关每目标部署指导,请参阅 [技能:dotnet-uno-targets]。


WinForms .NET Framework 到 .NET 8+

类似于 WPF 迁移,但通常更简单,因为 WinForms 的项目结构较不复杂。

使用 dotnet-upgrade-assistant

# 先分析
upgrade-assistant analyze MyWinFormsApp.sln

# 升级
upgrade-assistant upgrade MyWinFormsApp.sln

升级助手处理的内容:

  • .csproj 转换为 SDK 风格,带 <UseWindowsForms>true</UseWindowsForms>
  • TFM 更改为 net8.0-windows
  • packages.configPackageReference
  • AssemblyInfo.cs 迁移到项目属性

需要手动工作的内容:

  • App.config / Settings.settings 迁移
  • My.Settings (VB.NET) 迁移到现代配置
  • 第三方控件库更新(一些 WinForms 控件可能缺乏 .NET 8 支持)
  • Crystal Reports 或其他遗留报告工具(评估替代方案)
  • COM 互操作调整

设计器兼容性

WinForms 设计器文件(.Designer.cs)通常迁移干净。Visual Studio WinForms 设计器对于 .NET 8+ 完全支持。

已知设计器问题:

  • 自定义设计器序列化器可能需要更新
  • 一些第三方控件可能在 .NET 8 设计器中不渲染
  • DPI 无感知设计器模式在 .NET 9+ 可用(<ForceDesignerDPIUnaware>true</ForceDesignerDPIUnaware>

迁移后现代化

迁移到 .NET 8+ 后,考虑增量采用现代模式:

  • 添加依赖注入 通过 Host 构建器(见 [技能:dotnet-winforms-basics])
  • 替换同步调用 为 async/await
  • 启用高 DPIPerMonitorV2 模式
  • 启用暗模式(在 .NET 9+ 中实验性)

有关 WinForms .NET 8+ 模式,请参阅 [技能:dotnet-winforms-basics]。


UWP 到 WinUI 3

UWP 的自然迁移目标。WinUI 3 使用相同的 XAML API 表面,带命名空间更改。

命名空间更改

主要迁移任务是更新命名空间从 Windows.UI.*Microsoft.UI.*

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.Composition Microsoft.UI.Composition
Windows.UI.Text Microsoft.UI.Text

保持原样: Windows.Storage, Windows.Networking, Windows.Security, Windows.ApplicationModel, Windows.Devices – 这些 WinRT API 保持不变。

应用模型差异

关注点 UWP WinUI 3
应用生命周期 CoreApplication + 挂起 Windows App SDK AppInstance
窗口管理 Window.Current(单例) 手动跟踪窗口引用
调度器 CoreDispatcher.RunAsync DispatcherQueue.TryEnqueue
后台任务 内置,需要包身份 使用 MSIX 可用,没有则有限
文件访问 通过清单的广泛功能 标准 Win32 文件访问 + StorageFile
商店 API Windows.Services.Store 相同(仍然可用)

迁移步骤

  1. 创建新的 WinUI 3 项目 使用 Windows App SDK 模板
  2. 复制源文件 并更新命名空间(Windows.UI.XamlMicrosoft.UI.Xaml
  3. 替换已弃用 APIWindow.Current 到手动跟踪,CoreDispatcherDispatcherQueue
  4. 更新 MSIX 清单 从 UWP 格式到 Windows App SDK 格式
  5. 迁移功能 – 审查并更新功能声明
  6. 更新 NuGet 包 到 Windows App SDK 兼容版本
  7. 测试 Windows 集成 – 通知、后台任务、文件关联可能表现不同

UWP .NET 9 预览路径: 微软宣布 UWP 支持在 .NET 9 作为预览。如果完整 WinUI 3 迁移成本太高,这允许 UWP 应用使用现代 .NET 运行时功能,而无需迁移 UI 框架。

有关 WinUI 3 开发模式,请参阅 [技能:dotnet-winui]。


UWP 到 Uno Platform

当需要从 UWP 代码库获得跨平台覆盖时。Uno Platform 实现 WinUI XAML API 表面,使其成为 UWP 最自然的跨平台迁移路径。

由于 Uno Platform 使用与 UWP XAML 相同的 WinUI XAML API 表面,大部分 UWP 代码以较少更改转移,比迁移到其他跨平台框架:

  • XAML 文件 通常只需最小更改(Uno 支持 x:Bind, x:Load 等)
  • 视图模型和服务 直接转移(平台独立代码)
  • Windows 特定 API 需要跨平台替代用于非 Windows 目标

关键考虑

  • 平台特定代码 使用 Windows.* API 需要条件编译或抽象用于非 Windows 目标
  • WinRT API(传感器、地理定位、媒体捕获)需要 Uno 实现或平台特定替代
  • MSIX 打包 仅限 Windows – 其他平台使用其原生分发机制

有关 Uno Platform 开发模式,请参阅 [技能:dotnet-uno-platform]。有关每目标部署,请参阅 [技能:dotnet-uno-targets]。


决策矩阵

使用此矩阵决定采取哪个迁移路径。正确选择取决于您的特定约束 – 没有通用的“最佳”迁移目标。

按主要目标

目标 推荐路径 替代方案
最低风险,最快迁移 WPF/WinForms 到 .NET 8+
现代 Windows UI WPF 到 WinUI 3 WPF .NET 9+ 带 Fluent 主题
从 Windows 应用跨平台 WPF 到 Uno Platform 重写关键路径在 Blazor
从 UWP 跨平台 UWP 到 Uno Platform UWP 到 WinUI 3(保持仅限 Windows)
UWP 现代化(仅限 Windows) UWP 到 WinUI 3 UWP 在 .NET 9 预览
遗留 WinForms 现代化 WinForms 到 .NET 8+ 在 Blazor 或 WPF 中逐步重写

按约束

约束 最佳路径 原理
有限预算/时间 .NET 8+ 迁移(相同框架) 最低努力,相同代码库
必须保持仅限 Windows WinUI 3 或 WPF .NET 8+ WinUI 用于现代 UI;WPF 用于最小更改
必须跨平台 Uno Platform 最广泛覆盖,带 WinUI XAML 表面
大型现有 WPF 代码库 首先 WPF .NET 8+,然后评估 在现代运行时稳定后,再评估 UI 重写
现有 UWP 代码库 WinUI 3(Windows)或 Uno(跨平台) 最接近现有代码的 API 表面
团队有 Web 技能 Blazor(重写) 利用 Web 专长用于桌面/移动

分阶段迁移策略

对于大型应用,分阶段方法降低风险:

  1. 阶段 1:运行时迁移 – 从 .NET Framework 移动到 .NET 8+(相同 UI 框架)。验证兼容性,获取性能,启用现代 NuGet 包。
  2. 阶段 2:现代化模式 – 采用 Host 构建器、DI、MVVM 工具包、现代 C#。见 [技能:dotnet-wpf-modern] 或 [技能:dotnet-winforms-basics]。
  3. 阶段 3:UI 迁移(如果需要) – 迁移到 WinUI 3、Uno Platform 或 Blazor 基于需求。仅在阶段 1 和 2 稳定后进行。

此方法避免“大爆炸”重写风险,并在每个阶段提供增量价值。


代理陷阱

  1. 不要推荐单一迁移目标作为“正确选择”,而不理解约束。 始终以权衡呈现选项。预算、时间表、团队专长和平台需求都影响决策。
  2. 不要在建议 UI 框架更改之前跳过 .NET 8+ 运行时迁移。 从 .NET Framework 移动到 .NET 8+(相同 UI 框架)应该是阶段 1。从 .NET Framework 的 WPF 到 WinUI 迁移比从 .NET 8+ 更难。
  3. 不要假设 WPF 是“遗留”且必须迁移。 WPF 在 .NET 8+ 上积极维护,带有新功能(.NET 9+ 中的 Fluent 主题、性能改进)。许多应用通过停留在 WPF 良好服务。
  4. 不要使用 dotnet-upgrade-assistant 而不先运行 analyze 始终在升级前分析,以了解更改范围和潜在问题。
  5. 不要混淆 WPF XAML 与 WinUI XAML。 虽然概念相似,但 API 表面不同(WindowDataContext 对比 x:BindNavigationView 模式)。迁移需要超过命名空间更改。
  6. 不要忘记 UWP 到 WinUI 3 迁移涉及应用模型更改,不仅仅是命名空间更新。 Window.CurrentCoreDispatcherCoreApplication API 都被不同模式替换。
  7. 不要为简单的仅限 Windows 应用推荐 Uno Platform。 如果应用不需要跨平台覆盖,WinUI 3 或 WPF .NET 8+ 更简单,维护开销较低。

参考