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

问题描述 投票:6回答:3

我的问题出现在.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值?在这种情况下,OverridesDefaultStyleContentPresenter属性没有帮助。

任何想法?

c# wpf xaml styles textblock
3个回答
12
投票

请参见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>

5
投票

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


0
投票

关于两个选项:

  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>
© www.soinside.com 2019 - 2024. All rights reserved.