none
ContentPresenter foreground for a button overridden by TextBlock foreground RRS feed

  • Question

  • Hi,

    My style for the "Foreground" for a Button seems always overridden by the TextBlock "Foreground", as long as they are assigned at runtime (using "DynamicResources"). I need to assign the colors at runtime since the users need to change the themes at runtime.

    Here is the code snippets:

    <!--In the Common.xmal, loaded at application level as a merged ResourceDictionary:-->

      <Style TargetType="{x:Type TextBlock}">
            <Setter Property="FontFamily" Value="{DynamicResource FontFamilyUS}"/>
            <Setter Property="FontSize" Value="12"/>
            <Setter Property="Foreground" Value="{DynamicResource NormalTextBrush}"/>
        </Style>

     <Style TargetType="{x:Type Button}">
            <Setter Property="SnapsToDevicePixels" Value="False" />
            <Setter Property="FontSize" Value="12" />
            <Setter Property="Foreground" Value="{DynamicResource NormalButtonTextBrush}" />

    ...

    </Style>

     

    <!--In the one of the themes, loaded at run-time that gets added to the MergedDictionaries. I have a couple of them so that the user can switch to different themes.-->

    <SolidColorBrush x:Key="NormalTextBrush" Color="Gray" />
    <SolidColorBrush x:Key="NormalButtonTextBrush" Color="Wheat" />

     

    So my question is how do I get to assign the color for the text in my button? Thanks!

     

     

     

    • Edited by smallbug Friday, May 7, 2010 6:15 PM
    Friday, May 7, 2010 5:17 PM

Answers

  • Hi Smallbug,

    I performed tests in both Visual Studio 2008 and Visual Studio 2010 based on your description but didn't reproduce the problem. The Forground of the Button isn't overridden by the TextBlock's Foreground even if I use DynamicResource reference. The following is the complete code in my test.

    Dictionary1.xaml

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <SolidColorBrush x:Key="NormalTextBrush" Color="Red" />
        <SolidColorBrush x:Key="NormalButtonTextBrush" Color="Green" />
    </ResourceDictionary>

    Dictionary2.xaml

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="FontFamily" Value="{DynamicResource FontFamilyUS}"/>
            <Setter Property="FontSize" Value="12"/>
            <Setter Property="Foreground" Value="{DynamicResource NormalTextBrush}"/>
        </Style>

        <Style TargetType="{x:Type Button}">
            <Setter Property="SnapsToDevicePixels" Value="False" />
            <Setter Property="FontSize" Value="12" />
            <Setter Property="Foreground" Value="{DynamicResource NormalButtonTextBrush}" />
        </Style>
    </ResourceDictionary>

    Window1.xaml

    <Window x:Class="WpfApplicationTest.Window1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="Window2" Height="300" Width="300">
        <Window.Resources>
             <ResourceDictionary>
               <ResourceDictionary.MergedDictionaries>           
                <ResourceDictionary Source="Dictionary1.xaml"/>
                <ResourceDictionary Source="Dictionary2.xaml"/>
               </ResourceDictionary.MergedDictionaries>
              </ResourceDictionary>
        </Window.Resources>
      
        <StackPanel>        
            <TextBlock Text="Text Block"/>
            <Button Content="Button"/>
        </StackPanel>
    </Window>

    Is there any difference between your code and mine?

    Sincerely,
    Linda Liu


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    • Marked as answer by Linda Liu Friday, May 14, 2010 2:45 AM
    Wednesday, May 12, 2010 8:34 AM

All replies

  • As a matter of fact, I found out the typed style for TextBlock even overrides the hard coded foreground color for a button, as long as the "Foreground" is a "DynamicResource":

    <Button Foreground="Aqua">Submit</Button>

    The text label for the button doesn't show up as Aqua but in "NormalTextBrush".

    Friday, May 7, 2010 6:14 PM
  • Hi Smallbug,

    I performed tests in both Visual Studio 2008 and Visual Studio 2010 based on your description but didn't reproduce the problem. The Forground of the Button isn't overridden by the TextBlock's Foreground even if I use DynamicResource reference. The following is the complete code in my test.

    Dictionary1.xaml

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <SolidColorBrush x:Key="NormalTextBrush" Color="Red" />
        <SolidColorBrush x:Key="NormalButtonTextBrush" Color="Green" />
    </ResourceDictionary>

    Dictionary2.xaml

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="FontFamily" Value="{DynamicResource FontFamilyUS}"/>
            <Setter Property="FontSize" Value="12"/>
            <Setter Property="Foreground" Value="{DynamicResource NormalTextBrush}"/>
        </Style>

        <Style TargetType="{x:Type Button}">
            <Setter Property="SnapsToDevicePixels" Value="False" />
            <Setter Property="FontSize" Value="12" />
            <Setter Property="Foreground" Value="{DynamicResource NormalButtonTextBrush}" />
        </Style>
    </ResourceDictionary>

    Window1.xaml

    <Window x:Class="WpfApplicationTest.Window1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="Window2" Height="300" Width="300">
        <Window.Resources>
             <ResourceDictionary>
               <ResourceDictionary.MergedDictionaries>           
                <ResourceDictionary Source="Dictionary1.xaml"/>
                <ResourceDictionary Source="Dictionary2.xaml"/>
               </ResourceDictionary.MergedDictionaries>
              </ResourceDictionary>
        </Window.Resources>
      
        <StackPanel>        
            <TextBlock Text="Text Block"/>
            <Button Content="Button"/>
        </StackPanel>
    </Window>

    Is there any difference between your code and mine?

    Sincerely,
    Linda Liu


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    • Marked as answer by Linda Liu Friday, May 14, 2010 2:45 AM
    Wednesday, May 12, 2010 8:34 AM
  • I'm having a similar problem - if I define my styles in Window.Resources everything works as expected. Once I move them out to a ResourceDictionary the foreground will always be whatever value the default textblock is.

    Here's everything in a single window, which works as expected:

    <Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
    x:Class="TestBed.MainWindow"
    x:Name="Window"
    Title="MainWindow"
    Width="640" Height="480">
    <Window.Resources>
    <Style TargetType="{x:Type TextBlock}">
    <Setter Property="Foreground" Value="Black" />
    </Style>
    <Style x:Key="ButtonFocusVisual">
    <Setter Property="Control.Template">
    <Setter.Value>
    <ControlTemplate>
    <Rectangle Stroke="Black" StrokeDashArray="1 2" StrokeThickness="1" Margin="2" SnapsToDevicePixels="true"/>
    </ControlTemplate>
    </Setter.Value>
    </Setter>
    </Style>
    <LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
    <GradientStop Color="#F3F3F3" Offset="0"/>
    <GradientStop Color="#EBEBEB" Offset="0.5"/>
    <GradientStop Color="#DDDDDD" Offset="0.5"/>
    <GradientStop Color="#CDCDCD" Offset="1"/>
    </LinearGradientBrush>
    <SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>
    <Style TargetType="{x:Type Button}">
    <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
    <Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
    <Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Foreground" Value="White"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="Template">
    <Setter.Value>
    <ControlTemplate TargetType="{x:Type Button}">
    <Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" RenderDefaulted="{TemplateBinding IsDefaulted}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}">
    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True"/>
    </Microsoft_Windows_Themes:ButtonChrome>
    <ControlTemplate.Triggers>
    <Trigger Property="IsKeyboardFocused" Value="true">
    <Setter Property="RenderDefaulted" TargetName="Chrome" Value="true"/>
    </Trigger>
    <Trigger Property="ToggleButton.IsChecked" Value="true">
    <Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
    </Trigger>
    <Trigger Property="IsEnabled" Value="false">
    <Setter Property="Foreground" Value="#ADADAD"/>
    </Trigger>
    </ControlTemplate.Triggers>
    </ControlTemplate>
    </Setter.Value>
    </Setter>
    </Style>
    </Window.Resources>
    <StackPanel x:Name="LayoutRoot">
    <Button Content="Button" />
    </StackPanel>
    </Window>

    But if I move those same styles over to a ResourceDictionary, the Foreground of the button switches to black.

    Updated MainWindow:

    <Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
    x:Class="TestBed.MainWindow"
    x:Name="Window"
    Title="MainWindow"
    Width="640" Height="480">

    <StackPanel x:Name="LayoutRoot">
    <Button Content="Button" />
    </StackPanel>
    </Window>

     

    ResourceDictionary:

    <ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Style TargetType="{x:Type TextBlock}">
    <Setter Property="Foreground" Value="Black" />
    </Style>
    <Style x:Key="ButtonFocusVisual">
    <Setter Property="Control.Template">
    <Setter.Value>
    <ControlTemplate>
    <Rectangle Stroke="Black" StrokeDashArray="1 2" StrokeThickness="1" Margin="2" SnapsToDevicePixels="true"/>
    </ControlTemplate>
    </Setter.Value>
    </Setter>
    </Style>
    <LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
    <GradientStop Color="#F3F3F3" Offset="0"/>
    <GradientStop Color="#EBEBEB" Offset="0.5"/>
    <GradientStop Color="#DDDDDD" Offset="0.5"/>
    <GradientStop Color="#CDCDCD" Offset="1"/>
    </LinearGradientBrush>
    <SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>
    <Style TargetType="{x:Type Button}">
    <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
    <Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
    <Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Foreground" Value="White"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="Template">
    <Setter.Value>
    <ControlTemplate TargetType="{x:Type Button}">
    <Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" RenderDefaulted="{TemplateBinding IsDefaulted}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}">
    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True"/>
    </Microsoft_Windows_Themes:ButtonChrome>
    <ControlTemplate.Triggers>
    <Trigger Property="IsKeyboardFocused" Value="true">
    <Setter Property="RenderDefaulted" TargetName="Chrome" Value="true"/>
    </Trigger>
    <Trigger Property="ToggleButton.IsChecked" Value="true">
    <Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
    </Trigger>
    <Trigger Property="IsEnabled" Value="false">
    <Setter Property="Foreground" Value="#ADADAD"/>
    </Trigger>
    </ControlTemplate.Triggers>
    </ControlTemplate>
    </Setter.Value>
    </Setter>
    </Style>
    </ResourceDictionary>

     

    And my App.xaml because someone will ask for it:

    <Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="TestBed.App"
    StartupUri="MainWindow.xaml">
    <Application.Resources>
    <!-- Resources scoped at the Application level should be defined here. -->
    <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="ResourceDictionary.xaml"/>
    </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
    </Application.Resources>
    </Application>

    www.LeonTerry.com
    Friday, June 4, 2010 8:30 PM