在开发 WPF 类库时,由于类库里面没有存在 App.xaml.cs 文件,而在对单个 XAML 进行开发时,设计器将会因为找不到资源文件的存在,而拿不到资源。本文告诉大家简单的方法,给设计器设置仅在设计时引用的资源

在 WPF 的 XAML 中,如果对每个 XAML 控件都引用相同的资源,此时设计时将可以愉快的跑起来,然而在运行时将会重复创建资源影响性能。在开发 WPF 应用时,在入口项目里面,因为入口处有 App.xaml 文件,在这个文件里面加上了各个项目的引用,此时设计器就能知道当前项目引用的 XAML 资源字典,因此设计器就能工作

但是在开发类库的时候,类库不知道最终的入口项目是哪个,因此也就不知道当前程序在运行的时候,将会找不到引用

最佳的方法是和 Blend 一样,在设计时让设计器引用上某些资源,这样设计器就能工作

实现方法是在类库里面添加特殊的文件,这个特殊的文件有文件夹和命名的要求,这是在 VisualStudio 的设计器里面写常量固定的路径

在项目里面新建 Properties 文件夹,在 Properties 文件夹里面新建 DesignTimeResources.xaml 资源字典文件,大概如下

这个文件的命名规则是有约定的,不推荐自己修改。在 csproj 上添加如下代码

  <ItemGroup>
<Page Update="Properties\DesignTimeResources.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
<ContainsDesignTimeResources>true</ContainsDesignTimeResources>
</Page>
</ItemGroup>

上面代码核心就是 ContainsDesignTimeResources 这个属性。理论上可以给任意的 xaml 文件设置这个属性,但是 XAML 设计器在很多 VS 版本上只读取此路径的文件

在 DesignTimeResources.xaml 资源字典添加对其他资源字典的引用,即可实现让类库的设计器找到资源,而在运行时是不会加载资源到内存

例如我新建了类库项目 JeenalerenenearWerjilakaw 项目。我在 JeenalerenenearWerjilakaw 项目里面添加了资源字典 ColorBrushResourcesDictionary.xaml 资源字典,在里面存放颜色画刷,代码如下

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:JeenalerenenearWerjilakaw">
<SolidColorBrush x:Key="Brush.ColorBrush.ThemeColorBrush">#FF565656</SolidColorBrush>
</ResourceDictionary>

而我期望在 JeenalerenenearWerjilakaw 项目的自定义控件 UserControl1.xaml 上使用这个 Brush.ColorBrush.ThemeColorBrush 资源,如下面代码

  <Grid>
<Border Background="{StaticResource Brush.ColorBrush.ThemeColorBrush}" Margin="10,10,10,10"></Border>
</Grid>

此时的设计器和代码都不能工作,将会在设计器提示找不到资源

接下来新建 Properties\DesignTimeResources.xaml 资源字典文件,在这个资源字典文件里面添加如下代码

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../ColorBrushResourcesDictionary.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

在 JeenalerenenearWerjilakaw 的 csproj 添加如下代码

  <ItemGroup>
<Page Update="Properties\DesignTimeResources.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
<ContainsDesignTimeResources>true</ContainsDesignTimeResources>
</Page>
</ItemGroup>

当前的 csproj 的所有代码看起来如下

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

  <PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup> <ItemGroup>
<Page Update="Properties\DesignTimeResources.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
<ContainsDesignTimeResources>true</ContainsDesignTimeResources>
</Page>
</ItemGroup>
</Project>

以上代码是用在 SDK 风格的 csproj 文件上,如果当前项目文件非 sdk 风格,请参阅 从以前的项目格式迁移到 VS2017 新项目格式

接下来保存代码,然后关闭 VisualStudio 清理缓存文件,打开 VisualStudio 可以看到,当前设计器和代码都能工作

本文代码放在 githubgitee 欢迎下载执行

WPF Design Time Support (Part 2) · jbe2277/waf Wiki

然而在有 Resharper 的 VisualStudio 上,这个配置在 Resharper 2020 的一些版本是不认识的,此时将会让 Resharper 找不到资源引用,而没有自动跳转和补全的功能。好在 Resharper 对于项目格式的支持不够好,咱可以使用黑科技来解决此问题。在 Resharper 的 2021 版本也修了这个问题,因此在新版本的 Resharper 是不需要加以下代码

在 Resharper 中,将会根据 ApplicationDefinition 定义去读取应用资源文件,但是在读取时将会忽略 Condition 内容。于是咱就可以尝试创建一个叫 App_MakeReshaperHappy.xaml 的文件,用来让 Resharper 开森。在 csproj 中添加如下代码,用来引用应用资源,但实际上又不会用上此资源

    <ApplicationDefinition Include="App_MakeReshaperHappy.xaml" Condition="false">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>

上面代码中,使用了 Condition 为 false 让构建时实际忽略了此文件,否则将会在构建时报告不能在 WPF 类库中定义 ApplicationDefinition 元素。为什么不能叫 App.xaml 文件?原因是在 SDK 风格的 csproj 中,默认将会加上 EnableDefaultApplicationDefinition 自动加上默认的 ApplicationDefinition 元素。只要有文件叫 App.xaml 的,那么将会自动识别为 ApplicationDefinition 元素,此元素将会让 WPF 构建时报告不能在类库中定义。而如果设置 EnableDefaultApplicationDefinition 为 false 那 Resharper 又会不认此文件,经过了 lsj 工具人的摸索,发现使用上文方法是最稳的

App_MakeReshaperHappy.xaml 文件里面存放以下代码,用来让 Resharper 智能感知能在设计时找到资源

<Application x:Class="App_MakeReshaperHappy" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!--这个文件只是为了让Reshaper的智能感知开心-->
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!--以下替换为你自己的路径,我推荐引用的是设计时资源文件-->
<ResourceDictionary Source="Properties/DesignTimeResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

以上代码必须要自己定义类型,然后继承 Application 同时有 x:Class 内容才可以。这个文件的文件名和类名要求一定包含 App 这三个字符,同时文件名和类名需要相同

以上代码放在 githubgitee 欢迎下载执行

WPF 给类库设置设计时使用的资源字典的更多相关文章

  1. WPF获取和设置应用程序范围的资源

    设置资源: Application.Current.Resources["ApplicationScopeResource"] = Brushes.White; 使用代码获取资源: ...

  2. 【WPF学习】第三十五章 资源字典

    如果希望在多个项目之间共享资源,可创建资源字典.资源字典只是XAML文档,除了存储希望使用的资源外,不做其他任何事情. 一.创建资源字典 下面是一个资源字典示例,它包含一个资源: <Resour ...

  3. [WPF 学习] 3.用户控件库使用资源字典的困惑

    项目需要(或者前后端分离的需要),前端我使用了用户控件库,由后端用代码加载和控制. 然而用户控件库没法指定资源字典,于是在用户控件的xaml文件里面手工添加了资源字典 <UserControl. ...

  4. wpf控件设计时支持(3)

    原文:wpf控件设计时支持(3) wpf设计时调试 编辑模型 装饰器 1.wpf设计时调试 为了更好的了解wpf设计时框架,那么调试则非常重要,通过以下配置可以调试控件的设计时代码 (1)将启动项目配 ...

  5. WPF 判断一个对象是否是设计时的窗口类型,而不是运行时的窗口

    原文:WPF 判断一个对象是否是设计时的窗口类型,而不是运行时的窗口 当我们对 Window 类型写一个附加属性的时候,在属性变更通知中我们需要判断依赖对象是否是一个窗口.但是,如果直接判断是否是 W ...

  6. WPF 引用第三方库的控件在设计器加上设计时数据和属性

    本文告诉大家如何在 VisualStudio 2022 的 XAML 设计器中,在设计时给第三方控件加上设计用的属性和数据的方法 此功能要求使用不低于 VisualStudio 2019 的 16.8 ...

  7. wpf控件设计时支持(1)

    原文:wpf控件设计时支持(1) 这部分内容几乎是大家忽略的内容,我想还是来介绍一下. 本篇源码下载 1.属性元数据 在vs IDE中,在asp.net,winfrom等开发环境下,右侧的Proper ...

  8. wpf控件设计时支持(2)

    原文:wpf控件设计时支持(2) 这篇介绍在wpf设计时集合项属性添加项的定义和自定义控件右键菜单的方法 集合项属性设计时支持 1.为集合属性设计器识别具体项类型 wpf设计器允许定义集合项的类型,如 ...

  9. [No0000AE]在 Visual Studio 中调试 XAML 设计时异常

    在 Visual Studio 中进行 WPF, UWP, Silverlight 开发时,经常会遇到 XAML 设计器由于遭遇异常而无法正常显示设计器视图的情况.很多时候由于最终生成的项目在运行时并 ...

  10. 在 Visual Studio 中调试 XAML 设计时异常

    在 Visual Studio 中进行 WPF, UWP, Silverlight 开发时,经常会遇到 XAML 设计器由于遭遇异常而无法正常显示设计器视图的情况.很多时候由于最终生成的项目在运行时并 ...

随机推荐

  1. 记录--求你了,别再说不会JSONP了

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 JSONP是一种很远古用来解决跨域问题的技术,当然现在实际工作当中很少用到该技术了,但是很多同学在找工作面试过程中还是经常被问到,本文将带 ...

  2. 虚拟DOM的理解与总结

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 1. 对虚拟DOM的理解? 从本质上来说,Virtual Dom是一个JavaScript对象,通过对象的方式来表示DOM结构.将页面的状 ...

  3. 记录--短视频滑动播放在 H5 下的实现

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 短视频已经无数不在了,但是主体还是使用 app 来承载的.本文讲述 H5 如何实现 app 的视频滑动体验. 无声胜有声,一图顶百辩,且看 ...

  4. FFmpeg开发笔记(六)如何访问Github下载FFmpeg源码

    ​学习FFmpeg的时候,经常要到GitHub下载各种开源代码,比如FFmpeg的源码页面位于https://github.com/FFmpeg/FFmpeg.然而国内访问GitHub很不稳定,经常打 ...

  5. Docker Commands Diagram

  6. 工具推荐-sourcetree

    工具推荐-sourcetree 简介 简单好用的win系统下的git可视化软件 支持ssh免密登录 一键暂存和上传到开源仓库 开源免费 安装 下载sourcetree sourcetree下载 下载g ...

  7. CSP:Object as Point同会议论文,相似思想用于人脸和行人检测 | CVPR 2019

    CSP将目标定义为中心点和尺寸,通过网络直接预测目标的中心和寸尺,相对于传统的RCNN类型检测算法轻量化了不少.整体思想与Object as Points撞车了,真是英雄所见略同   来源:晓飞的算法 ...

  8. java反序列化-CC1

    CC1 目录 CC1 1.Transformer接口 2.Transformer的实现类 ConstantTransformer ChainedTransformer InvokerTransform ...

  9. Scala 函数至简原则

    (1)return 可以省略,Scala 会使用函数体的最后一行代码作为返回值(2)如果函数体只有一行代码,可以省略花括号(3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)(4) ...

  10. HandlerInterceptorAdapter和HandlerInterceptor的区别

    其实归根揭底一个是抽象类,一个是接口,HandlerInterceptor是接口,它提供了所有方法,让开发人员必须实现所有方法, 而HandlerInterceptorAdapter是一个抽象类,它提 ...