[WPF]是时候将WPF控件库从.Net Framework升级到.NET Core 3.1

1. 升级到Core的好处

去年中我曾考虑将我的控件库项目Kino.Toolkit.Wpf升级到.NET Core,不过很快放弃了,因为当时.NET Core是预览版,编译WPF还需要使用最新的Visual Studio 2019,这样作为一个教学项目不够友好。到了今天.NET Core 3.1都出来了,已经正式支持WPF和Winform,Visual Studio 2019也已经普及,我觉得应该是时候将我的控件库升级到.NET Core。那么现在是WPF正式迁移到.NET Core的好时机吗?我认为还不是,把一个成熟的WPF程序迁移到.NET Core风险任然较大,而且不见得有多少好处。但对各种WPF类库/控件库来说情况又不一样了,为了可以满足更多的用户,让控件库可以同时支持.NET Framework和.NET Core十分重要;而且通常类库对其它组件的依赖较少,升级的风险没那么大。所以要玩.NET Core的WPF,从类库/控件库开始是一个好的选择。

具体来说,让WPF控件库升级到.NET Core具体来说有以下的好处:

  • 巨大的时髦值,最近WPF开发时髦值很低,.NET Core是我们为数不多可以蹭到时髦值、面向时髦值编程的机会。
  • 新的csproj文件,顺便升级到新的SDK-style csproj文件有很多好处,包括更简洁可读的文件,新的NuGet引用方式,可以指定多个开发框架等。
  • 更方便打包Nuget。

升级到.NET Core 3.1有以下步骤:

  • 分析可移植性
  • 迁移到 NuGet 引用
  • 迁移csproj项目文件

这篇文章我会以我的Kino.Toolkit.Wpf项目作为示例,master分支不升级,而core升级到core 3.1以作比较。需要注意的是,WPF控件库的升级和其它.NET项目的升级有一点出入,这篇文章的升级方式不一定适合其它.NET Core项目。

2. .NET 可移植性分析

在升级前,保险起见需要使用.NET 可移植性分析器分析项目在目标.NET平台上的可移植性。安装.NET Portability Analyzer这个Visual Studio的扩展后在Visual Studio的解决方案资源管理器窗口选中要分析的项目,右键选择“Analyze Project Portability”:

在结果窗口选择“Open Report”:

结果将以Excel的方式显示,像这种小项目一般不会出现什么问题,图个安心:

3. 迁移到 PackageReference NuGet 引用

引用了Nuget包的旧.NET Framework项目会将引用的Nuget信息记录在packages.config文件中,例如在示例的项目中,这个文件的内容如下:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.CodeAnalysis.FxCopAnalyzers" version="2.9.8" targetFramework="net45" developmentDependency="true" />
  <package id="Microsoft.CodeAnalysis.VersionCheckAnalyzer" version="2.9.8" targetFramework="net45" developmentDependency="true" />
  <package id="Microsoft.CodeQuality.Analyzers" version="2.9.8" targetFramework="net45" developmentDependency="true" />
  <package id="Microsoft.NetCore.Analyzers" version="2.9.8" targetFramework="net45" developmentDependency="true" />
  <package id="Microsoft.NetFramework.Analyzers" version="2.9.8" targetFramework="net45" developmentDependency="true" />
  <package id="Microsoft.Xaml.Behaviors.Wpf" version="1.1.19" targetFramework="net45" />
</packages>

新的SDK-Style项目文件使用PackageReference节点记录Nuget的引用信息,这样做的好处包括精简内容与以及不再需要额外的packages.config文件,所以我们必须将packages.config迁移到 PackageReference。要迁移到PackageReference,先尽可能升级引用的Nuget包,然后选中项目中的packages.config,在右键菜单中选中“将 packages.config 迁移到 PackageReference”:

在弹出的对话框会列出顶级的依赖项和传递的依赖项,还会询问是否将后者升级到顶级依赖项,这个项目无需做任何改变,直接点击“确定”:

迁移完成后会得到一个报告:

打开Kino.Toolkit.Wpf.csproj,会发现少了些东西,但多了下面这段,这段就是经过精简的Nuget引用,在“管理Nuget程序包”的页面也可以看到已安装的Nuget变少了:

完成这一步后还原Nuget包,该升级的升级,运行下确认升级没有出错,然后进行下一步。

4. 迁移csproj项目文件

接下来需要迁移csproj项目文件到新的SDK-Style格式,不过在那以前好歹先确保自己已经安装了.NET Core 3.1 SDK,随便新建一个WPF (.NET Core)项目,这里我选择了自定义控件库项目:

生成的项目的csproj项目文件如下:

<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

</Project>

其中SDK 是一组可生成 .NET Core 代码的 MSBuild 任务和目标,Sdk="Microsoft.NET.Sdk.WindowsDesktop"标识这是一个.NET Core的WinForms或WPF项目。

PropertyGroup这一节表明这是个.NET Core 3.1项目,并使用WPF。如果是应用程序项目的话还需要<OutputType>WinExe</OutputType>,因为这是个类库项目所以缺少了这一节。

为了可以支持多个框架,需要将<TargetFramework>这一节改为下面内容,注意TargetFramework变为TargetFrameworks,因为从单一框架变成多个框架。

<TargetFrameworks>net462;netcoreapp3.1</TargetFrameworks>

现在可以把这些内容复制到Kino.Toolkit.Wpf.csproj,加上前面提到的<PackageReference>节点的内容,完整内容如下:

  <PropertyGroup>
    <TargetFrameworks>net462;netcoreapp3.1</TargetFrameworks>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers">
      <Version>2.9.8</Version>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.Xaml.Behaviors.Wpf">
      <Version>1.1.19</Version>
    </PackageReference>
  </ItemGroup>

</Project>

重新加载项目,还原Nuget包重新编译等一系列操作都完成后,可以见到项目已经完成迁移了:

5. 处理其它问题

迁移项目文件后会有一些问题,首先是以前从项目中排除的文件又包含在项目里了,毕竟以前那么复杂的项目文件可不是吃素的,这么简单粗暴迁移过来总会丢一些内容。重新将他们从项目中排除,项目文件多了以下这些内容,以表明这些文件都是多余的(如果文件真是多余的也可以直接删掉):

<ItemGroup>
  <Compile Remove="Class1.cs" />
  <Compile Remove="SkeletonScreen\DispatcherContainer.cs" />
</ItemGroup>
<ItemGroup>
  <None Remove="ClassDiagram1.cd" />
</ItemGroup>

AssemblyInfo.cs这个文件有很多版本号之类的信息,现在都在项目文件中声明,所以这些信息全都变得多余,会引起编译错误,全部删掉只保留下面这些就好:

// [assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
    ResourceDictionaryLocation.None,
    ResourceDictionaryLocation.SourceAssembly)
]

[assembly: XmlnsPrefix("https://github.com/DinoChan/Kino.Toolkit.Wpf", "kino")]
[assembly: XmlnsDefinition("https://github.com/DinoChan/Kino.Toolkit.Wpf", "Kino.Toolkit.Wpf")]
[assembly: XmlnsDefinition("https://github.com/DinoChan/Kino.Toolkit.Wpf", "Kino.Toolkit.Wpf.Primitives")]

其中ThemeInfo指示项目使用默认的Themes\Generic.xaml主题文件,对WPF项目是必不可少。XmlnsPrefix等内容是为了方便在XAML内引用这个项目,具体可见命名空间这一段内容。

然后重新填一填应用程序和打包信息,可以看到项目文件中多了不少内容:

<PropertyGroup>
  <TargetFrameworks>net462;netcoreapp3.1</TargetFrameworks>
  <UseWPF>true</UseWPF>
  <ApplicationIcon>Assets\Images\kino.ico</ApplicationIcon>
  <Version>1.6.0</Version>
  <Copyright>Copyright ?  2019</Copyright>
  <PackageLicenseExpression>https://raw.githubusercontent.com/DinoChan/Kino.Toolkit.Wpf/master/LICENSE</PackageLicenseExpression>
  <PackageProjectUrl>https://github.com/DinoChan/Kino.Toolkit.Wpf</PackageProjectUrl>
  <PackageIcon>Logo.png</PackageIcon>
  <RepositoryUrl>https://github.com/DinoChan/Kino.Toolkit.Wpf</RepositoryUrl>
<PropertyGroup>
  <TargetFrameworks>net462;netcoreapp3.1</TargetFrameworks>
  <UseWPF>true</UseWPF>
  <ApplicationIcon>Assets\Images\kino.ico</ApplicationIcon>
  <Version>1.6.0</Version>
  <Copyright>Copyright ?  2019</Copyright>
  <PackageLicenseExpression></PackageLicenseExpression>
  <PackageProjectUrl>https://github.com/DinoChan/Kino.Toolkit.Wpf</PackageProjectUrl>
  <PackageIcon>Logo.png</PackageIcon>
  <RepositoryUrl>https://github.com/DinoChan/Kino.Toolkit.Wpf</RepositoryUrl>
  <PackageTags>WPF Control Toolkit Xaml</PackageTags>
  <Description>A set of wpf toolkit.</Description>
  <NeutralLanguage>en-US</NeutralLanguage>
</PropertyGroup>

具体的打包成Nuget的过程可以参考林德熙的这篇文章:

VisualStudio 使用新项目格式快速打出 Nuget 包

6. 结语

实际上WPF项目要迁移到.NET Core会复杂很多,目前我也只是在控件库上尝试。但换成新SDK-Style项目格式没什么坏处,可以放手一拼(只要不我让我负责任)。

有些项目可能还需要安装Microsoft.Windows.Compatibility,更多的信息请看下面给出的参考链接。

7. 参考

Migrating WPF Apps to .NET Core 3.0 - WPF _ Microsoft Docs

.NET Core 的 csproj 格式的新增内容 - .NET Core CLI _ Microsoft Docs

从 .NET Framework 移植到 .NET Core - .NET Core _ Microsoft Docs

将 Contoso Expenses 应用迁移到 .NET Core 3 _ Microsoft Docs

.NET 可移植性分析器 - .NET _ Microsoft Docs

将传统 WPF 程序迁移到 DotNetCore 3.0 - hippieZhou - 博客园

将基于 .NET Framework 的 WPF 项目迁移到基于 .NET Core 3 - walterlv

VisualStudio 使用新项目格式快速打出 Nuget 包

原文地址:https://www.cnblogs.com/dino623/p/Migrating_WPF_Control_Library_to_NET_Core.html

时间: 2024-10-03 01:09:13

[WPF]是时候将WPF控件库从.Net Framework升级到.NET Core 3.1的相关文章

WPF控件库之Menu控件

WPF控件库之Menu(1) Menu 是一个控件,使用该控件可以对那些与命令或事件处理程序相关联的元素以分层方式进行组织.每个 Menu 可以包含多个 MenuItem 控件.每个 MenuItem 都可调用命令或调用 Click 事件处理程序.MenuItem 也可以有多个 MenuItem 元素作为子项,从而构成子菜单. Menu 是一个控件,使用该控件可以对那些与命令或事件处理程序相关联的元素以分层方式进行组织.每个 Menu 可以包含多个 MenuItem 控件.每个 MenuItem

WPF 控件库——仿制Chrome的ColorPicker

一.观察 项目中的一个新需求,需要往控件库中添加颜色拾取器控件,因为公司暂时还没有UI设计大佬入住,所以就从网上开始找各种模样的ColorPicker,找来找去我就看上了谷歌浏览器自带的,它长这个样: 看上去不错,可以搞!搞之前得观察一下这里面可能的一些坑.对WPF而言,圆角阴影等效果都是基本操作,这里就不说了. 首先我们注意到上图中有两个拖动条,一个背景是可见光谱,另一个背景是颜色渐变和方块平铺的叠加.因为需求里没有屏幕取色的功能,所以在拖动条左侧的拾取图标可以去掉,只保留当前颜色预览,这样会

WPF 控件库——可拖动选项卡的TabControl

原文:WPF 控件库--可拖动选项卡的TabControl 一.先看看效果 二.原理 1.选项卡大小和位置 这次给大家介绍的控件是比较常用的TabControl,网上常见的TabControl样式有很多,其中一部分也支持拖动选项卡,但是带动画效果的很少见.这也是有原因的,因为想要做一个不失原有功能,还需要添加动画效果的控件可不是一行代码的事.要做成上图中的效果,我们不能一蹴而就,最忌讳的是一上来就想实现所有效果. 一开始,我们最好先用Blend看看原生的TabControl样式模板部分是如何实现

《Dotnet9》系列-开源C# WPF控件库强力推荐

本系列已介绍三款开源C# WPF控件库,其中一款国外的,另两款是国内的,大家如有比较好的开源C# WPF控件库,欢迎向Dotnet9推荐,您可在本文下方留言,谢谢您对dotnet的关注和支持,让我们期待dotnet更好的明天,以下是Dotnet9已完成的3篇开源C# WPF控件库推荐文章: 1.<Dotnet9>系列-开源C# WPF控件库1<MaterialDesignInXAML>强力推荐. 2.<Dotnet9>系列-开源C# WPF控件库2<Panuon.

(四)开源C# WPF控件库《AduSkin – UI》

微信公众号:[Dotnet9的博客],网站:[Dotnet9],问题或建议:[请网站留言], 如果对您有所帮助:[欢迎赞赏]. (四)开源C# WPF控件库<AduSkin> 追求极致,永臻完美 A Beautiful WPF Control UI 一款简单漂亮的WPF UI,融合部分开源框架的组件,为个人定制的UI,可供学者参考. 阅读导航 关于<AduSkin> 1.1 控件库全貌 1.2 动态修改主题色 1.3 技术交流 基于<AduSkin>控件库衍生的Case

WPF实现炫酷Loading控件

Win8系统的Loading效果还是很不错的,网上也有人用CSS3等技术实现,研究了一下,并打算用WPF自定义一个Loading控件实现类似的效果,并可以让用户对Loading的颗粒(Particle)背景颜色进行自定义,话不多说,直接上代码: 1.用VS2012新建一个WPF的用户控件库项目WpfControlLibraryDemo,VS自动生成如下结构: 2.删除UserControl1.xaml,并新建一个Loading的CustomControl(不是UserControl),如下图所示

.NET CORE(C#) WPF 方便的实现用户控件切换(祝大家新年快乐)

微信公众号:Dotnet9,网站:Dotnet9,问题或建议:请网站留言, 如果对您有所帮助:欢迎赞赏. .NET CORE(C#) WPF 方便的实现用户控件切换(祝大家新年快乐) 快到2020年了,祝大家新年快乐,今年2019最后一更,谢谢大家支持! 阅读导航 本文背景 代码实现 本文参考 源码 1. 本文背景 一个系统主界面,放上一个菜单,点击菜单在客户区切换不同的展示界面,这是很常规的设计,见下面展示效果图: 左侧一个菜单,点击菜单,右侧切换界面,界面切换动画使用MD控件的组件实现(自己

转载 [WPF][C#]在WPF中内嵌WindowsForm控件-使用WindowsFormsControlLibrary

[WPF][C#]在WPF中内嵌WindowsForm控件-使用WindowsFormsControlLibrary 在[WPF][C#]在WPF中内嵌WindowsForm控件一文中为各位介绍了直接在WPF中使用XAML来嵌入Windows Form控件的作法,不过不是每个人都喜欢写XAML,而且有时候会需要把已经存在的Windows Form应用程序嵌入到WPF中,所以这次就来跟大家介绍怎么使用参考dll档的方式,把dll中的Windows Form加到WPF中. 都说了要使用Windows

WPF 10天修炼 - 内容控件

WPF内容控件 在WPF中,所有呈现在用户界面上的对象都称为用户界面元素.但是只有派生自System.Windows.Controls.Control类的对象才称为控件.内容控件通常是指具有Content属性的控件,Content属性并非定义在每个控件中,而是定义在基类System.Windows.Controls命名空间的ContentControl类中.注意:Content属性只接收单个内容元素. WPF内容控件分类 1.  直接继承ContentControl的控件 2.  继承Heade