我的问题出现在.NET 3.5 SP1中的WPF中,可以描述如下:
我有一个默认的Style
会击中用户界面中的所有TextBlock
元素。看起来就是这样:
<Style TargetType="{x:Type TextBlock}">
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
<Setter Property="Foreground" Value="Red"/>
</Style>
这对所有TextBlock
都适用。除此之外,我还有一个Button
样式,包括一个看起来像这样的ControlTemplate
(缩短):
<Style x:Key="MyButtonStyle" TargetType="{x:Type Button}" BasedOn="{x:Null}">
<Setter Property="Foreground" Value="Green"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Border"
Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
Height="24"
BorderBrush="{TemplateBinding BorderBrush}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
TextBlock.Foreground="{TemplateBinding Foreground}"/>
</Border>
<ControlTemplate.Triggers>...</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
注意TextBlock.Foreground="{TemplateBinding Foreground}"
中的ContentPresenter
行。这应该将按钮文本设置为绿色,并且实际上在Visual Studio的设计器视图中也是如此。但是,当我编译并运行程序时,按钮文字为红色,文字颜色由默认的TextBlock
样式设置。我已通过Snoop对此进行了验证。
如何防止默认的TextBlock
样式覆盖TextBlock.Foreground
值?在这种情况下,OverridesDefaultStyle
的ContentPresenter
属性没有帮助。
任何想法?
请参见this link的答案5
发生这种情况是因为ContentPresenter创建一个TextBlock对于字符串内容,并且因为TextBlock不在视觉树中,而是将查找到应用程序级别资源。如果您定义样式应用程序中的TextBlock级别,那么它将应用于ContentControl中的这些TextBlock
一种解决方法是定义一个System.String的DataTemplate,其中我们可以显式使用默认值TextBlock显示内容。您可以将DataTemplate放在您定义的同一本词典TextBlock样式使这个DataTemplate将应用于任何受ContentPresenter影响的您的风格。
尝试将此添加到ResourceDictionary
<DataTemplate DataType="{x:Type sys:String}">
<TextBlock Text="{Binding}">
<TextBlock.Resources>
<Style TargetType="{x:Type TextBlock}"/>
</TextBlock.Resources>
</TextBlock>
</DataTemplate>
最好不要覆盖TextBlock的默认样式。到目前为止,我能想到的最好的主意是为Control创建一种样式,并将其应用于所有顶级窗口。
<!-- App.xaml -->
<Application.Resources>
<Style x:Key="RedStyle" TargetType="{x:Type Control}">
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
<Setter Property="Foreground" Value="Red"/>
</Style>
</Application.Resources>
<!-- MainWindow.xaml -->
<Window Style="{StaticResource RedStyle}" ...>
...
</Window>
请参见此处以获取更多详细信息:http://www.ikriv.com/dev/dotnet/wpftextstyle/
关于两个选项:
尝试将此添加到ResourceDictionary
<DataTemplate DataType="{x:Type sys:String}">
<TextBlock Text="{Binding}">
<TextBlock.Resources>
<Style TargetType="{x:Type TextBlock}"/>
</TextBlock.Resources>
</TextBlock>
</DataTemplate>
最好不要覆盖TextBlock的默认样式。到目前为止,我能想到的最好的主意是为Control创建一种样式,并将其应用于所有顶级窗口。
我会建议一种替代方法,并使用附加的Dependency属性,例如
namespace AttachedProperties
{
public static class TextBlockExtensions
{
public static bool GetUseAppThemeStyle(DependencyObject obj)
{
return (bool)obj.GetValue(UseAppThemeStyleProperty);
}
public static void SetUseAppThemeStyle(DependencyObject obj, bool value)
{
obj.SetValue(UseAppThemeStyleProperty, value);
}
// Using a DependencyProperty as the backing store for UseAppThemeStyle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty UseAppThemeStyleProperty =
DependencyProperty.RegisterAttached("UseAppThemeStyle", typeof(bool), typeof(TextBlockExtensions), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits));
}
}
注意:默认情况下,可以将其设置为true或false
然后有了名称空间:
xmlns:attachedProperties="clr-namespace:AttachedProperties"
设置默认样式:
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource {x:Type TextBlock}}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(attachedProperties:TextBlockExtensions.UseAppThemeStyle), RelativeSource={RelativeSource Mode=Self}}" Value="True">
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
然后,如果您需要获得默认值,则可以只设置一种样式的附加属性:
<Style x:Key="blueButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="attachedProperties:TextBlockExtensions.UseAppThemeStyle" Value="False" />
<Setter Property="Foreground" Value="Blue" />
</Style>
或直接在按钮上:
<Button attachedProperties:TextBlockExtensions.UseAppThemeStyle="False" Foreground="Blue">I'm blue da ba dee da ba die...</Button>