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

7
我的问题出现在 .NET 3.5 SP1 中的 WPF,并描述如下:
我有一个默认的样式,适用于 UI 中所有的 TextBlock 元素。它看起来是这样的:
<Style TargetType="{x:Type TextBlock}">
   <Setter Property="TextTrimming" Value="CharacterEllipsis"/>
   <Setter Property="Foreground" Value="Red"/>
</Style>

这对于所有的都有效。除此之外,我还有一个包括ControlTemplate
3个回答

15
请参考链接中的答案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>

2
谢谢您的回答。有两件事情我不太明白:1. 即使 ContentPresenter 创建的 TextBlock 不在 VisualTree 中,它应该还是会接受我设置在 TextBlock.Foreground 中的值,对吗?2. 使用您描述的 DataTemplate,我只能为 ContentPresenter 元素中的所有文本使用一种样式,对吗? - Holger Adam
据我理解,它只会确保其他TextBlock样式不被捕捉到。但是我可能错了,我以前用过它,没有遇到任何问题。 - Fredrik Hedblad
@HA:此外,这仅在由ContentControl的Content创建TextBlock时使用。您仍然可以像示例中所做的那样进行设置,例如设置前景色等。或者我误解了问题? - Fredrik Hedblad
1
不,你说得对。起初我确实没有完全理解。然而,我决定不使用这个解决方案,因为如果我在按钮内放置一个图像、矩形或其他东西,它就会失败。相反,我从默认的 TextBlock 样式中移除了前景属性。这样对我来说效果更好。无论如何,感谢你的帮助。 - Holger Adam
4
覆盖 System.String 的数据模板是一个不好的想法,因为它会丢失下划线到键盘快捷方式以及 ContentStringFormat 功能。这让我陷入了困境。更多细节请参见此处:http://www.ikriv.com/dev/dotnet/wpftextstyle/StringTemplate.shtml - Ivan Krivyakov
您可以使用 AccessText 替代 TextBlock 以保留键盘快捷键功能。 - Joachim Mairböck

6

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

关于这两个选项:

  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的样式,并将其应用于所有顶层窗口。

我建议采用另一种方法,使用附加依赖属性。

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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接