如何将 WPF 桌面应用升级到 .NET 8
本文介绍如何将 Windows Presentation Foundation(WPF) 桌面应用升级到 .NET 8。 尽管 WPF 运行在作为跨平台技术的 .NET 上,它仍然是一个仅限于 Windows 的框架。 可以使用 .NET 升级助手升级以下 WPF 相关的项目类型:
- WPF 项目
- 控件库
- .NET 库
如果要从 .NET Framework 升级到 .NET,不妨查看与 WPF .NET 的差异文章和从 .NET Framework 移植到 .NET指南。
先决条件
- Windows 操作系统
- 面向 .NET 8 的 Visual Studio 2022 17.7 或更高版本
- 面向 .NET 7 的 Visual Studio 2022 17.1 或更高版本
- 适用于 Visual Studio 的 .NET 升级助手扩展
演示应用
本文是在升级 Web 收藏夹示例 项目的上下文中编写的,可以从 .NET 示例 GitHub 存储库下载该项目。
启动升级
如果要升级多个项目,请从没有依赖项的项目开始。 在 Web 收藏夹示例中,WebSiteRatings 项目取决于 StarVoteControl 库,因此应首先升级 StarVoteControl。
提示
请务必备份代码,例如使用源代码管理工具或保存副本。
使用以下步骤升级 Visual Studio 中的项目:
在 解决方案资源管理器 窗口中右键单击 StarVoteControl 项目,然后选择 升级:
将打开一个新选项卡,提示你选择要执行升级的方式。
选择“就地项目升级”。
接下来,选择目标框架。 根据要升级的项目类型,将显示不同的选项。 .NET Standard 2.0 是一个不错的选择,如果库不依赖于 WPF 等桌面技术,并且可由 .NET Framework 项目和 .NET 项目使用。 但是,最新的 .NET 版本在语言和编译器方面提供了许多超过 .NET Standard 的改进。
选择 .NET 8.0,然后选择 下一步。
将显示一个树,其中包含与项目相关的所有项目,例如代码文件和库。 可以升级单个工件或整个项目,而升级整个项目是默认选项。 选择 升级选择 开始升级。
升级完成后,将显示结果:
具有实体绿色圆圈的项目被升级,而具有空绿色圆圈的项目则被跳过。 跳过的生成工件意味着升级助手没有找到任何可以升级的内容。
升级应用支持库后,请升级主应用。
升级应用
升级所有支持库后,可以升级主应用项目。 执行以下步骤:
- 右键单击 解决方案资源管理器 窗口中的 WebSiteRatings 项目,然后选择 升级:
- 选择“就地项目升级”作为升级模式。
- 为目标框架选择 .NET 8.0,然后选择 下一步。
- 保留选中所有项目,然后选择“升级选择”。
升级完成后,将显示结果。 如果项目具有警告符号,则表示有一条笔记可供你阅读,可以通过展开该项来执行此操作。
生成干净的内部版本
升级项目后,清理并编译它。
- 右键单击“解决方案资源管理器”窗口中的“WebSiteRatings”项目,然后选择“清理”。
- 右键单击“解决方案资源管理器”窗口中的“WebSiteRatings”项目,然后选择“生成”。
如果应用程序遇到任何错误,可以在 错误列表 窗口中找到这些错误,并建议如何修复它们。
升级后步骤
如果你的项目正在从 .NET Framework 升级到 .NET,请查看从 .NET Framework 升级到 .NET 后的现代化一文中的信息。
升级后,你将想要:
检查 NuGet 包。
.NET 升级助手将某些包升级到了新版本。 使用本文中提供的示例应用,
Microsoft.Data.Sqlite
NuGet 包已从 1.0.0 升级到 8.0.x。 但是,1.0.0 取决于SQLite
NuGet 包,但 8.0.x 会删除该依赖项。SQLite
NuGet 包仍由项目引用,但不再需要它。 可以从项目中删除SQLite
和SQLite.Native
NuGet 包。清理旧的 NuGet 包。
不再需要 packages.config 文件,并且可以从项目中删除,因为 NuGet 包引用现已在项目文件中声明。 此外,名为 包的本地 NuGet 包缓存文件夹位于项目的文件夹或父文件夹中。 可以删除此本地缓存文件夹。 新的 NuGet 包引用使用一个名为 .nuget\packages的全局缓存文件夹,该文件夹位于用户的配置文件目录中。
删除
System.Configuration
库。大多数 .NET Framework 应用引用
System.Configuration
库。 升级后,可能仍直接引用此库。System.Configuration
库使用 app.config 文件向应用提供运行时配置选项。 对于 .NET,此库已替换为System.Configuration.ConfigurationManager
NuGet 包。 删除对库的引用,并将 NuGet 包添加到项目。检查对应用进行现代化改造的位置。
自 .NET 发布以来,API 和库发生了很大的变化。 在大多数情况下,.NET Framework 无法访问这些改进。 通过升级到 .NET,现在可以访问更现代的库。
接下来的部分描述了您可以对本文使用的示例应用进行现代化的领域。
现代化:Web 浏览器控件
WPF 示例应用引用的 WebBrowser 控件基于 Internet Explorer(已过期)。 .NET 的 WPF 可以使用基于 Microsoft Edge 的 WebView2 控件。 完成以下步骤以升级到新的 WebView2 Web 浏览器控件:
添加
Microsoft.Web.WebView2
NuGet 包。在 MainWindow.xaml 文件中:
将控件导入根元素中的 wpfControls 命名空间:
<mah:MetroWindow x:Class="WebSiteRatings.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro" xmlns:local="clr-namespace:WebSiteRatings" xmlns:vm="clr-namespace:WebSiteRatings.ViewModels" xmlns:VoteControl="clr-namespace:StarVoteControl;assembly=StarVoteControl" xmlns:wpfControls="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf" Loaded="MetroWindow_Loaded" mc:Ignorable="d" Title="My Sites" Height="650" Width="1000">
在声明
<Border>
元素的位置下,删除WebBrowser
控件并将其替换为wpfControls:WebView2
控件:<Border Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" BorderThickness="1" BorderBrush="Black" Margin="5"> <wpfControls:WebView2 x:Name="browser" ScrollViewer.CanContentScroll="True" /> </Border>
编辑 MainWindow.xaml.cs 代码隐藏文件。 更新
ListBox_SelectionChanged
方法,将browser.Source
属性设置为有效的 Uri。 此代码以前作为字符串传入网站 URL,但 WebView2 控件需要使用Uri
。private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { var siteCollection = (ViewModels.SiteCollection)DataContext; if (siteCollection.SelectedSite != null) browser.Source = new Uri(siteCollection.SelectedSite.Url); else browser.NavigateToString("<body></body>"); }
根据应用用户运行的 Windows 版本,他们可能需要安装 WebView2 运行时。 有关详细信息,请参阅 WPF 应用中的 WebView2 入门。
现代化:appsettings.json
.NET Framework 使用 App.config 文件来加载应用程序的设定,例如连接字符串和日志提供程序。 .NET 现在使用 appsettings.json 文件进行应用设置。 .NET 通过 System.Configuration.ConfigurationManager
NuGet 包支持 App.config 文件,Microsoft.Extensions.Configuration
NuGet 包提供对 appsettings.json 的支持。
随着其他库升级到 .NET,它们通过支持 appsettings.json 而不是 App.config实现现代化。例如,已为 .NET 6+ 升级的 .NET Framework 中的日志记录提供程序不再对设置使用 App.config。 最好遵循他们的指导,并尽量避免使用 App.config。
将 appsettings.json 与 WPF 示例应用配合使用
例如,升级 WPF 示例应用后,对本地数据库的连接字符串使用 appsettings.json。
删除
System.Configuration.ConfigurationManager
NuGet 包。添加
Microsoft.Extensions.Configuration.Json
NuGet 包。将文件添加到名为 appsettings.json的项目。
将 appsettings.json 文件设置为复制到输出目录。
在“解决方案资源管理器”中选择文件后,使用“属性”窗口通过 Visual Studio 设置“复制到输出”设置。 或者,可以直接编辑项目并添加以下
ItemGroup
:<ItemGroup> <Content Include="appsettings.json"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> </ItemGroup>
将 App.config 文件中的设置迁移到新的 appsettings.json 文件。
在 WPF 示例应用中,app.config 仅包含单个连接字符串。 编辑 appsettings.json 文件以定义连接字符串:
{ "ConnectionStrings": { "database": "DataSource=sqlite.db;" } }
编辑 App.xaml.cs 文件,实例化加载 appsettings.json 文件的配置对象,添加的行会突出显示:
using System.Windows; using Microsoft.Extensions.Configuration; namespace WebSiteRatings { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App : Application { public static IConfiguration Config { get; private set; } public App() { Config = new ConfigurationBuilder() .AddJsonFile("appsettings.json") .Build(); } } }
在 .\Models\Database.cs 文件中,更改
OpenConnection
方法以使用新的App.Config
属性。 这需要导入Microsoft.Extensions.Configuration
命名空间:using Microsoft.Data.Sqlite; using System.Collections.Generic; using Microsoft.Extensions.Configuration; namespace WebSiteRatings.Models { internal class Database { public static SqliteConnection OpenConnection() => new SqliteConnection(App.Config.GetConnectionString("database")); public static IEnumerable<Site> ReadSites()
GetConnectionString
是由Microsoft.Extensions.Configuration
命名空间提供的扩展方法。