前言
C# 写客户端的时候,WinForm 真的很折磨,WPF 越写越顺手,最近的需求,必须要写在 WinForm 里面,没办法只能另辟蹊径,反正之前也嵌套过,只是没找到办法引入资源字典文件、第三方控件库,这次从头开始写,势必要搞定他。
问题
在 Visual Studio 创建一个 WPF 项目后,可以在 App.xaml 中直接全局注册想使用的资源文件,但是在 WinForm 中嵌套进 WPF 程序时,没有这个 App.xaml 全局注册资源的地方
解决
根据标签内容 <Application.Resources> 很容易明白,App.xaml 本质上是向 Application 对象中写入资源信息,但是在当前嵌套程序中直接往里面写的时候发现 Application 对象是 null,后来发现是 WinForm 默认不含 Application 全局变量,所以写入资源文件时直接手动创建一个即可
1、在 WPF 主窗口初始化前创建 Application 对象
1
2
3
4
|
if (Application.Current == null)
{
new Application();
}
|
2、随即引入资源文件
1
2
3
|
Application.Current.Resources.MergedDictionaries
.Add((ResourceDictionary)Application
.LoadComponent(new Uri("/Plugin.Demo;component/styles/Dictionary.xaml", UriKind.Relative)));
|
附加
目前发现这样全局注册资源文件的弊病就是在 XAML 文件编辑预览时会出现无法解析资源关键字的提示信息
在针对非全局资源文件时,可以通过在 View 文件的 Resources 标签里添加 ResourcesDictionary 的方式引入资源文件,这样的好处是可以实时预览效果
1
2
3
4
5
6
7
|
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Plugin.Demo;component/Styles/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
|
补充
在写的时候发现引入第三方控件库时出现了报错无法找到 dll 组件的位置,后排查后发现原因在于我得项目结构时 WinForm 程序当作启动项目,WPF 程序作为被动项目引入,在导入第三方库时仅仅在 WPF 项目上引入会报错
解决办法也很简单:直接在启动项目中引入第三方空间库即可(不需要在启动项目中做其他操作)
WPF 引入资源的几种方式
XAML 引入资源
窗口、控件处引入
1
2
3
4
5
6
7
8
9
10
11
12
|
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- 相对路径引入内部资源 -->
<ResourceDictionary Source="/styles/Dictionary.xaml"/>
<!-- 相对路径引入外部资源 -->
<ResourceDictionary Source="/Plugin.Demo;component/styles/Dictionary.xaml"/>
<!-- 绝对路径外部资源 -->
<ResourceDictionary Source="pack://application:,,,/Plugin.Demo;component/styles/Dictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
|
全局引入
1
2
3
4
5
6
7
|
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/lugin.Demo;component/styles/Dictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
|
代码引入
1
2
3
4
5
6
7
8
9
|
var app = Application.Current.Resources.MergedDictionaries;
//绝对路径(实测报错)
var rDic = new System.Windows.ResourceDictionary();
rDic.Source = new Uri("pack://application:,,,/HandyControl;component/Themes/Theme.xaml", UriKind.Absolute);
app.Add(rDic);
//相对路径
app.Add((ResourceDictionary)Application.LoadComponent(new Uri("/HandyControl;component/Themes/SkinDefault.xaml", UriKind.Relative)));
|
参考
「WPF 中资源字典(ResourceDictionary)的使用」
「关于 c#:Application.Current 和 App.Current 为 null」
「Winform 中使用 WPF Control(带资源)」
「WPF 引用资源字典的几种方式」