默认TextBlock样式覆盖按钮文本颜色

时间:2010-12-21 14:09:20

标签: c# wpf xaml styles textblock

我的问题出现在.NET 3.5 SP1中的WPF中,可以描述如下:

我的默认Style命中了我的UI中的所有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的{​​{1}}属性无效。

有什么想法吗?

3 个答案:

答案 0 :(得分:11)

请参阅this link

上的答案5
  

这发生的原因是因为   ContentPresenter创建一个TextBlock   对于字符串内容,从那以后   它不是可视树中的TextBlock   将查找到应用程序级别   资源。如果你定义一个风格   用于应用程序的TextBlock   等级,然后它将被应用于   ContentControl中的这些TextBlock

     

解决方法是定义一个   DataTemplate for System.String,其中   我们可以明确使用默认值   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>

答案 1 :(得分:4)

最好不要覆盖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/

答案 2 :(得分:0)

关于2个选项:

  1. @Fredrik Hedblad

尝试将其添加到ResourceDictionary

<DataTemplate DataType="{x:Type sys:String}">
    <TextBlock Text="{Binding}">
        <TextBlock.Resources> 
            <Style TargetType="{x:Type TextBlock}"/>
        </TextBlock.Resources>
    </TextBlock>
</DataTemplate>
  1. @Ivan Krivyakov

最好不要覆盖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>