在使用 VisualStudio 开发 WPF或WinForms应用时,打开UI文件的设计界面,我们可以从工具箱的控件列表中直接拖拽控件到界面上。通过这种方式,可以清晰的展示控件库中所有可用的控件,并且非常方便的将其添加到界面中。那么我们可以通过哪些方式将WPF/WinForms控件库中的控件添加到VisualStudio的工具箱呢?本文就对此做一个简单的总结。
我们知道,.NET Core 3.0 及以上版本提供了对 WPF/WinForm 框架的支持,而VS工具箱对其 .NET Framework 和 .NET(Core) 控件的支持存在一定的差异,所以接下来以 WPF 控件库为例,分别创建名为 MyWpfControlsForFramework 和 MyWpfControlsForCore 的 WPF 用户控件库,其目标框架分别为 .NET Framework 4.8 和 .NET 6,其中都包含一个名为 Control1 的控件,编译后分别得到对应的DLL文件。
1. WPF .NET Framework 控件
.NET Framework 的控件可以通过以下几个方式添加到VS工具箱中:
1.1 手动添加
新建 WPF .NET Framework 4.8 应用项目,双击打开 MainWindow.xaml
文件,进入设计界面,展开工具箱窗口,右键添加选项卡 MyWpfControls
,然后将之前生成的 MyWpfControlsForFramework.dll 拖到该选项卡下,即可完成添加,如下图:
1.2 通过 NuGet 安装
这种方式需要我们将库项目打包成 NuGet 包,并在包中添加 tools/VisualStudioToolsManifest.xml
文件,文件内容如下:
<FileList>
<File Reference = "MyWpfControlsForFramework.dll">
<ToolboxItems UIFramework="WPF" VSCategory="MyWpfControls">
<Item Type="MyWpfControlsForFramework.Control1" />
</ToolboxItems>
</File>
</FileList>
其中,Reference
是程序集名称,VsCategory
是选项卡名称,其中的Item
表示要添加到工具箱中的控件的完全限定名称。
这样,通过NuGet包管理器安装此包时就会将控件添加到VS工具箱。该方式支持 VS 2017 15.0 及以上版本。
1.3 Visual Studio Toolbox Controls Installer (TCI)
TCI 是 VS 的一项用于向工具箱安装控件的功能,它通过搜索注册表项的方式来查找控件。有3种方式可以利用此功能,下面介绍其中一种设置 AssemblyFoldersEx
注册表项的方式:
- 将程序集保存到某一自定义目录下,如:
C:\MyWpfAssemblies
; - 打开注册表编辑器,找到
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319\AssemblyFoldersEx
项; - 在
AssemblyFoldersEx
项下新建子项,名称自定义,例如MyWpfControls
,修改默认值为程序集所在目录C:\MyWpfAssemblies
; - 在
MyWpfControls
项下新建Toolbox
子项,在该子项中添加名为TabName
字符串值,值为要在VS工具箱中显示的选项卡名称,例如MyWpfControls
。
这样,工具箱在加载时,就会检查注册表,并将控件添加到其中。
另外,如果我们更新了程序集,例如新增了控件,那么就必须更新注册表项。因为只有这样,TCI才会更新工具箱中的控件。因此,我们可以在 Toolbox
项中添加一个名为 Version
的 DWORD值,值的数据没有要求,只是为了触发这一机制。那么在更新程序集后,也同时更新 Version
的值,就可以及时的更新工具箱中的控件。最终结果如下所示:
通过这种方式不需要添加对程序集的引用,即可在VS工具箱中显示控件,支持 VS 2010 及以上版本。另外,添加程序集和注册表的步骤可以通过“安装程序”来完成。
2. WPF .NET 6 控件
.NET 6 的控件可以通过以下几个方式添加到VS工具箱中:
2.1 通过 NuGet 安装
该方式与 .NET Framework 一样,需要我们将库项目打包成 NuGet 包,并在包中添加 tools/VisualStudioToolsManifest.xml
文件,文件内容与Framework一致。当然,为了打包方便,我们可以将该文件放到项目目录下,然后在项目文件中添加如下配置:
<PropertyGroup>
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);VSToolsManifest</TargetsForTfmSpecificContentInPackage>
</PropertyGroup>
<Target Name="VSToolsManifest">
<ItemGroup>
<TfmSpecificPackageFile Include="tools\VisualStudioToolsManifest.xml">
<PackagePath>tools</PackagePath>
</TfmSpecificPackageFile>
</ItemGroup>
</Target>
其中Include
是 VisualStudioToolsManifest.xml
文件相对项目文件的路径,PackagePath
是该文件最终在 NuGet 包中的目录路径。该方式支持 VS 2017 15.0 及以上版本。
2.2 将 NuGet 包添加到 NuGet Fallback 目录
使用这种方式,我们不需要在项目中添加对包的引用,即可在VS工具箱中显示其控件。
- 打开
C:\Program Files (x86)\NuGet\Config
目录,新建MyFallback.config
文件,文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<fallbackPackageFolders>
<add key="My NuGet Fallback Folder" value="C:\MyNuGetFallbackFolder" />
</fallbackPackageFolders>
</configuration>
其中,key
的值应避免和同目录下其他文件内的一致,value
是自定义的 Fallback 目录。
-
下载 nuget.exe;
-
执行以下指令将上一种方式生成的 NuGet 包扩展到 fallback 目录:
nuget.exe add MyWpfControlsForCore.nupkg -Source C:\MyNuGetFallbackFolder -Expand
最终,在 C:\MyNuGetFallbackFolder
中会新增一个MyWpfControlsForCore
目录。使用 nuget.exe 而不是简单的解压nupkg文件的原因是 nuget.exe 会生成一个 .nuget.metadata
文件,当 NuGet 恢复时需要此文件。
当使用安装程序安装此包时,建议将此扩展好的文件夹添加到安装程序中,由安装程序将其拷贝到用户机上,而不是在用户机上调用 nuget.exe。这种方式支持 VS 2019 16.7 Preview 2 及以上版本。
以上就是往 VisualStudio 工具箱中添加 WPF/WinForms 控件的几种方式,除此之外还有其他的几种方式,详情可以看参考链接。
参考
- https://github.com/microsoft/xaml-designer-extensibility/blob/main/documents/toolbox-population.md#toolbox-items-from-unreferenced-assemblies
- https://learn.microsoft.com/zh-cn/visualstudio/extensibility/creating-a-wpf-toolbox-control?view=vs-2022