0

I have a problem with a certain WPF style called HeadText with TargetType = "TextBlock". The style defines Foreground, FontSize and Effect. The first time a TextBlock is shown only the Foreground setter is not fired (text color stays black), FontSize and Effect are applied normally. When I remove the TextBlock from parent and return it back, then the foreground is also changed as it should.

Situation:

Presenter.dll assembly

  • class Presenter: Window, loads and displays my usercontrols.
  • Generic.xaml - Resource dictionary that contains styles.
  • Presenter.dll does not directly reference TestPresentable.dll.

TestPresentable.dll assembly

  • TestPresentable: UserControl, has a styled TextBlock.
  • TestPresentable.dll does not directly reference Presenter.dll.

MainApp.exe

  • references both previous assemblies,
  • instantiates MainWindow from Presenter.dll assembly,
  • instantiates TestPresentable from TestPresentable assembly,
  • sets MainWindow.ContentHost.Content = testPresentable

Relevant code:

Presenter.dll

// Themes/Generic.xaml
...
<Style TargetType="{x:Type TextBlock}" x:Key="HeadText">
    <Setter Property="Foreground" Value="#FFFFFFFF" />
    <Setter Property="Effect">
        <Setter.Value>
            <DropShadowEffect ShadowDepth="0" Color="#79000000" BlurRadius="3" Opacity="1" />
        </Setter.Value>
    </Setter>
    <Setter Property="FontSize" Value="24"/>
</Style>
...


// MainWindow.xaml
...
<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Presenter.dll;component/Themes/Generic.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>
<Grid>
    <ContentPresenter Name="ContentHost"/>
</Grid>
...

TestPresentable.dll

// TestPresentable.xaml
...
<TextBlock Text="{Binding SomeData}" Style="{DynamicResource HeadText}"/>
...
akjoshi
  • 15,374
  • 13
  • 103
  • 121
Boris B.
  • 4,933
  • 1
  • 28
  • 59

2 Answers2

7

It seems that there is something strange with TextBlock.Foreground in WPF since 3.5, see:

I've came up with a workaround using EventSetters and some codebehind for a ResourceDictionary. It's not pretty but will have to do if I want to have my styles independant of the main app. I'll post it here since it might be useful to someone and I'll keep the question open if someone post the right (or better) answer.

Workaround

In the ResorceDictionary XAML (e.g. Generic.xaml) add a Class property like so:

<!-- Generic.xaml -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Presenter.Themes.Generic">

Then add a codebehind cs file (e.g. Generic.xaml.cs) with the partial class you specified in the Class property of the ResourceDictionary:

// Generic.xaml.cs
partial class Generic { }

In the relevant style of the ResourceDictionary add an EventSetter for the Loaded event:

<!-- Generic.xaml -->
<Style TargetType="{x:Type TextBlock}" x:Key="HeadText">
    <EventSetter Event="Loaded" Handler="OnHeadTextLoaded"/>
    <Setter .../>
    <Setter .../>
    <Setter .../>
</Style>

In the Generic.xaml.cs add a handler for the Loaded event and set the desired Foreground

//Generic.xaml.cs
public void OnHeadTextLoaded(object sender, EventArgs args)
{
    var textBlock = sender as TextBlock;
    if (textBlock == null) return;
    textBlock.Foreground = new SolidColorBrush(Colors.White);
}
Community
  • 1
  • 1
Boris B.
  • 4,933
  • 1
  • 28
  • 59
1

I have a similar problem with the foreground colour not pulling through the first time the page loads. I've found that in my case if you hard code the FontFamily property in the xaml file where the TextBlock is located, then the foreground colour pulls through correctly the first time.

If you however just place the FontFamily property in the stylesheet, then the TextBlock will again just be black first time.

e.g.

// TestPresentable.xaml

...
Style="{DynamicResource HeadText}" **FontFamily="Arial"**... 
Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
FrancoisD
  • 11
  • 1