我创建了一个类库程序集,在其中创建自定义控件,并在 generic.xaml 文件中定义了默认样式。
这似乎是一个相当普遍的问题,只要很多人都在发布它。但是,我找不到任何有用的答案。
- generic.xaml 位于"主题"文件夹中。
- generix.xaml 文件"生成操作"设置为"页面"。
- ThemeInfo在我的AssemblyInfo.cs中正确定义。
在我的测试应用程序中,如果我手动将自定义控件程序集中的 generic.xaml 文件合并到应用程序 App.xaml 文件中,如下所示:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MyControlsAssembly;component/Themes/generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
则自定义控件的主题正确,但如果我不手动合并 generic.xaml,则控件将以默认的 Windows 主题显示。
你能告诉我我忘记了什么和/或做错了什么吗?
附加信息:
我的 ThemeInfo 程序集属性定义如下:
[assembly: ThemeInfo(ResourceDictionaryLocation.SourceAssembly, ResourceDictionaryLocation.SourceAssembly)]
(注意:结果与 ThemeInfo 属性的任意参数组合相同)
在"主题"文件夹中的 generic.xaml 文件旁边还有另外两个 .xaml 文件。
- "主题"文件夹中有一个子文件夹,该子文件夹本身包含另一个 .xaml 文件。
若要在我的自定义控件库中应用主题\Generic.xaml中的默认样式,我决定从成熟的开源控件库(MahApps)中寻求灵感。此项目为您提供了一个非常好的示例,说明如何构建和布局自定义控件库。
长话短说,若要在 Themes\Generic.xaml 中获取默认样式,您需要在自定义控件库的 AssemblyInfo.cs 文件中包含以下内容:
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
就我而言,我的自定义控件 AssemblyInfo.cs 如下所示:
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Markup;
[assembly: AssemblyCopyright("...")]
[assembly: ComVisible(false)]
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0.0")]
[assembly: AssemblyTitleAttribute("...")]
[assembly: AssemblyDescriptionAttribute("")]
[assembly: AssemblyProductAttribute("...")]
[assembly: AssemblyCompany("...")]
自定义控件构造函数中需要以下行:
public class MyCustomControl : Control
{
static MyCustomControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new FrameworkPropertyMetadata(typeof(MyCustomControl)));
}
}
然后,如果主题文件夹中有一个 generic.xaml 文件,则具有以下示例样式:
<Style TargetType="{x:Type local:MyCustomControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyCustomControl}">
<Border>
<Label>Testing...</Label>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
现在,样式将自动应用,而无需任何额外的合并。
就我而言,我忘记从标签中删除x:Key
<Style>
。
错:
<Style TargetType="controls:IpTextBox" x:Key="MyControlStyle">
正确:
<Style TargetType="controls:IpTextBox">
不确定这是否适用于 WPF,但它在 Silverlight 中对我有用:
构造 函数:
public class MyCustomControl : Control
{
static MyCustomControl()
{
this.Style = (Style)Application.Current.Resources["MyCustomControlStyle"];
}
}
风格:
<Style x:Key="MyCustomControlStyle" TargetType="{local:MyCustomControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{local:MyCustomControl}">
<Border>
<Label>Testing...</Label>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
自定义控件程序集中的以下属性,我遇到了同样的问题:
[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
将UltimateResourceFallbackLocation.Satellite
更改为UltimateResourceFallbackLocation.MainAssembly
或删除第二个参数完全解决了我的问题(如果您不需要定义程序集的中性语言,也可以删除该属性)。