通过Themes/Generic.xaml为WPF控件提供默认样式不生效
<p>1. 我有一个netframework4.8的类库项目,里面提供了一个自定义控件,然后我按照以下方法为控件提供了默认样式</p><p> a) 添加Themes\Generic.xaml文件,文件中提供自定义控件的默认样式</p>
<div class="cnblogs_code">
<pre><Style TargetType=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">MyControl</span><span style="color: rgba(128, 0, 0, 1)">"</span>>
<Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Template</span><span style="color: rgba(128, 0, 0, 1)">"</span>>
<Setter.Value>
<ControlTemplate TargetType=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">MyControl</span><span style="color: rgba(128, 0, 0, 1)">"</span>><span style="color: rgba(0, 0, 0, 1)">
//.......</span>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style></pre>
</div>
<p> </p>
<p> b) 在自定义控件的静态构造函数中,添加</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl)));</pre>
</div>
<p> 现在一切正常,Generic.xaml中定义的默认样式能够自动应用到我的自定义控件上</p>
<p>2. 后面我想把项目升级成net8.0,因为旧的代码是半成品并且代码很少,我就没有在旧项目上升级,而是直接新建了一个net8.0的类库项目,然后将关键代码拷贝了过去,结果默认样式不生效了。</p>
<p>3. 经过排查发现,原来是我在创建net8.0的项目时,误选择了“类库”模板而非“WPF用户控件库”模板,“WPF用户控件库”模板相对于“类库”模板,项目下多了一个AssemblyInfo.cs文件,内容如下</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">using System.Windows;<br><br>[assembly:ThemeInfo(
ResourceDictionaryLocation.None, </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">主题特定资源词典所处位置
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">(未在页面中找到资源时使用,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">或应用程序资源字典中找到时使用)</span>
ResourceDictionaryLocation.SourceAssembly <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">常规资源词典所处位置
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">(未在页面中找到资源时使用,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">、应用程序或任何主题专用资源字典中找到时使用)</span>
)]</pre>
</div>
<p>正是ThemeInfo特性指定了资源文件的位置。</p>
<p>ThemeInfoAttribute的构造函数有两个参数,分别表示特定于主题的资源文件的路径和非特定于主题的资源文件的路径。ResourceDictionaryLocation是一个枚举类型,当值等于SourceAssembly时,资源文件应放在Themes\目录下</p>
<div class="cnblogs_code">
<pre>public ThemeInfoAttribute(System.Windows.ResourceDictionaryLocation themeDictionaryLocation, System.Windows.ResourceDictionaryLocation genericDictionaryLocation);</pre>
</div>
<p>4. 最后解决方案有两个:</p>
<p> a) 在项目下创建AssemblyInfo.cs文件,为程序集提供ThemeInfo特性</p>
<p> b) (推荐)通过项目文件提供ThemeInfo特性,在csproject项目文件中添加以下代码</p>
<div class="cnblogs_code">
<pre><Project Sdk=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Microsoft.NET.Sdk</span><span style="color: rgba(128, 0, 0, 1)">"</span>><span style="color: rgba(0, 0, 0, 1)">
........
</span><ItemGroup>
<AssemblyAttribute Include=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">System.Windows.ThemeInfoAttribute</span><span style="color: rgba(128, 0, 0, 1)">"</span>>
<_Parameter1>System.Windows.ResourceDictionaryLocation.None</_Parameter1>
<_Parameter1_TypeName><span style="color: rgba(0, 0, 255, 1)">true</span></_Parameter1_TypeName>
<_Parameter2>System.Windows.ResourceDictionaryLocation.SourceAssembly</_Parameter2>
<_Parameter2_IsLiteral><span style="color: rgba(0, 0, 255, 1)">true</span></_Parameter2_IsLiteral>
</AssemblyAttribute>
</ItemGroup>
</Project></pre>
</div>
<p> </p><br><br>
来源:https://www.cnblogs.com/yangtb/p/18860425
頁:
[1]