8
votes

We are using global styles definitions for most of the types. We define then in the app.xaml file. When using TextBlock it is a problem to define a foreground color because it changes all the controls using TextBlock (Button's content color for example). How can we define a global style which will act only on specific TextBlock usages?

current problematic usage:

<Style TargetType={x:Type TextBlock}>
  <Setter Property="Foreground" Value="Red"/>
</Style>
3

3 Answers

2
votes

Since I don't think there is a way to differentiate “your” TextBlocks and those that are part of other controls, your options are quite limited.

  • You could create named Style and add Style="{StaticResource coloredTextBlock}" or Foreground="{StaticResource textBlockColor}" to all TextBlocks. This would be quite tedious and non-DRY.
  • You could create your own type that inherits from TextBlock and style that. This has some of the disadvantages of the above solution (you have to remember doing that). But it has much less repetition.
2
votes

This is because ContentPresenter creates a TextBlock for a string content, and since that TextBlock isn't in the visual tree, it will lookup to Application level resource. And if you define a style for TextBlock at Application level, then it will be applied to these TextBlock within ControlControls.

A workaround is to define a DataTemplate for System.String, where we can explicitly use a default TextBlock to display the content. You can place that DataTemplate in the same dictionary you define the TextBlock style so that this DataTemplate will be applied to whatever ContentPresenter effected by your style.

Add this to your Application resources and it should work for you -

<DataTemplate DataType="{x:Type system:String}">
  <TextBlock Text="{Binding}">
    <TextBlock.Resources>
      <Style TargetType="{x:Type TextBlock}"/>
    </TextBlock.Resources>
  </TextBlock>
</DataTemplate>

Declare a namespace in your xaml, if not referred already -

xmlns:system="clr-namespace:System;assembly=mscorlib"

EDIT : Check this sample where its working..

<Style TargetType="{x:Type TextBlock}">
   <Setter Property="Foreground" Value="Red"/>
</Style>

<DataTemplate DataType="{x:Type system:String}">
  <TextBlock Text="{Binding}">
     <TextBlock.Resources>
        <Style TargetType="{x:Type TextBlock}"/>
     </TextBlock.Resources>
  </TextBlock>
</DataTemplate>

<Style TargetType="{x:Type Button}">
  <Setter Property="Foreground" Value="Yellow"/>
</Style>

<Style TargetType="{x:Type Label}">
  <Setter Property="Foreground" Value="Blue"/>
</Style>
1
votes

Just provide a x:key in the style, like:

<Style x:Key="stRedTextBlock" TargetType={x:Type TextBlock}>
        <Setter Property="Foreground" Value="Red"/>
</Style>

and mention the key in the TextBlock control style, where ever you require this particular TextBlock style, like:

<TextBlock Name="textBlock1" Style="{StaticResource stRedTextBlock}" />