【发布时间】:2018-08-22 13:37:18
【问题描述】:
我正在尝试正确设置我的样式。因此,我为所有常见样式属性创建了一个外部ResourceDictionary,其中我定义了一个默认字体系列,如下所示:
<FontFamily x:Key="Default.FontFamily">Impact</FontFamily>
这样,当我更改这一行时,家庭会在所有地方发生变化。
使用和引用静态资源
现在我想在没有其他任何定义的地方使用这个默认字体系列,在大多数地方(但不是全部)。但是,我想保留为使用它的任何地方定义其他字体系列的能力。因此,我使用了我找到的 here 和 here 的示例,并为组框标题明确定义了默认字体:
<StaticResource x:Key="GroupBox.HeaderFontFamily" ResourceKey="Default.FontFamily"/>
我在包含在我的组框模板中的TextBlock 上使用它。
<Style x:Key="GroupBoxHeaderTextStyle" TargetType="{x:Type TextBlock}">
<Setter Property="FontFamily" Value="{StaticResource GroupBox.HeaderFontFamily}"/>
</Style>
到目前为止,这是有效的。但是,只要我添加另一行:
<StaticResource x:Key="GroupBox.HeaderFontFamily" ResourceKey="Default.FontFamily"/>
<StaticResource x:Key="FormLabel.FontFamily" ResourceKey="Default.FontFamily"/>
我抛出了这个异常:
异常:找不到名为“Hsetu.GroupBox.HeaderFontFamily”的资源。资源名称区分大小写。
所以我经历过 WPF 无法找到直接寻址的元素,当其后跟 StaticResource 时(是的,这也适用于静态资源以外的元素。例如,如果我尝试直接寻址字体系列 "Default.FontFamily",我会得到同样的错误,因为它在 StaticResource 元素之前)
使用 DynamicResource 并引用 StaticResource
我已尝试使用DynamicResource,如第二个示例中所建议的那样,我提供了上面的链接:
<DynamicResource x:Key="GroupBox.HeaderFontFamily" ResourceKey="Default.FontFamily"/>
<DynamicResource x:Key="FormLabel.FontFamily" ResourceKey="Default.FontFamily"/>
<Style x:Key="GroupBoxHeaderTextStyle" TargetType="{x:Type TextBlock}">
<Setter Property="FontFamily" Value="{StaticResource GroupBox.HeaderFontFamily}"/>
</Style>
这会引发以下错误:
ArgumentException:“System.Windows.ResourceReferenceExpression”不是属性“FontFamily”的有效值。
使用和引用 DynamicResource
在我的组框样式中使用DynamicResource 只会更改错误消息:
<DynamicResource x:Key="GroupBox.HeaderFontFamily" ResourceKey="Default.FontFamily"/>
<DynamicResource x:Key="FormLabel.FontFamily" ResourceKey="Default.FontFamily"/>
<Style x:Key="GroupBoxHeaderTextStyle" TargetType="{x:Type TextBlock}">
<Setter Property="FontFamily" Value="{DynamicResource GroupBox.HeaderFontFamily}"/>
</Style>
System.InvalidCastException:'无法将'System.Windows.ResourceReferenceExpression'类型的对象转换为'System.Windows.Media.FontFamily'类型。'
添加虚拟元素
因此,由于这个问题仅在我的StaticResource 后面跟着另一个时才会出现,所以我想在资源之间包含一个虚拟元素。
<StaticResource x:Key="GroupBox.HeaderFontFamily" ResourceKey="Default.FontFamily"/>
<Separator x:Key="Dummy"/>
<StaticResource x:Key="FormLabel.FontFamily" ResourceKey="Default.FontFamily"/>
现在,这行得通。 万岁!但是等一下……继续,我尝试使用第二个资源"FormLabel.FontFamily"
<Style x:Key="FormLabelStyle" TargetType="{x:Type Label}">
<Setter Property="FontFamily" Value="{StaticResource FormLabel.FontFamily}"/>
</Style>
这会引发另一个异常:
System.InvalidCastException:'无法将'System.Windows.Controls.Separator'类型的对象转换为'System.Windows.Media.FontFamily'类型。'
错误?
我什至根本没有使用Separator,所以这是怎么回事?我假设,在处理 StaticResource 时,WPF 实际上会尝试使用前面的元素——它只在开始时起作用,因为前面的元素偶然是 FontFamily——而不是 ResourceKey 引用的元素。同时,使前面的元素无法直接访问。为了证实我的怀疑,我将Separator 替换为另一个FontFamily。
<StaticResource x:Key="GroupBox.HeaderFontFamily" ResourceKey="Default.FontFamily"/>
<FontFamily x:Key="Dummy">Courier New</FontFamily>
<StaticResource x:Key="FormLabel.FontFamily" ResourceKey="Default.FontFamily"/>
确实,它有效,但标签现在使用 Courier New 字体而不是引用的 Impact 字体。
顺便说一句。这不仅发生在字体系列中,还发生在其他属性上(FontSize、BorderThickness、FontWeight 等)。那么,这实际上是 WPF 中的一个错误,还是 StaticResources 应该这样做(这对我来说没有任何意义)?我怎样才能在多个地方使用我的字体系列,只定义一次?
【问题讨论】:
标签: wpf staticresource