Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override Standard Theme in App.xaml

I am using the standard WPF theme Aero.NormalColor.xaml. And it works very well. However for the whole application, I would like to override the Foreground color of textboxes to red.

My first try is that

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary
                Source="/PresentationFramework.Aero, Version=3.0.0.0,
               Culture=neutral, PublicKeyToken=31bf3856ad364e35,
               ProcessorArchitecture=MSIL;component/themes/Aero.NormalColor.xaml">
            </ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>
        <Style TargetType="TextBox">
            <Setter Property="Foreground" Value="Red" />
        </Style>
    </ResourceDictionary>
</Application.Resources>

Well... all foreground color of textboxes become red. However all textboxes lose the theme style. Yes, I know I should add "BasedOn". My second try is add "BasedOn" in the style tag.

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary
                Source="/PresentationFramework.Aero, Version=3.0.0.0,
               Culture=neutral, PublicKeyToken=31bf3856ad364e35,
               ProcessorArchitecture=MSIL;component/themes/Aero.NormalColor.xaml">
            </ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>
        <Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
            <Setter Property="Foreground" Value="Red" />
        </Style>
    </ResourceDictionary>
</Application.Resources>

Exception is thrown. Same as this WPF : Extend Theme's style - StackOverflowException

Eventually, I achieve my goal by this.

In App.xaml

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary
                Source="/PresentationFramework.Aero, Version=3.0.0.0,
               Culture=neutral, PublicKeyToken=31bf3856ad364e35,
               ProcessorArchitecture=MSIL;component/themes/Aero.NormalColor.xaml">
            </ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

And in all windows and user control, I had to explicitly set

<UserControl.Resources>
    <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
        <Setter Property="Foreground" Value="Red" />
    </Style>
</UserControl.Resources>

The above code is copy and paste for many times and it is not easy to maintain. Does anyone know how to achieve my goal by just set foreground to red by one time?

like image 599
Alex Yeung Avatar asked Nov 23 '09 02:11

Alex Yeung


2 Answers

I think you can add the Style to a ResourceDictionary and merging that with the Aero theme like this:

<Application.Resources>
  <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
      <ResourceDictionary Source="/PresentationFramework.Aero, Version=3.0.0.0,
        Culture=neutral, PublicKeyToken=31bf3856ad364e35,
        ProcessorArchitecture=MSIL;component/themes/Aero.NormalColor.xaml">
      </ResourceDictionary>

      <!-- Adding the style to a resource dictionary -->
      <ResourceDictionary>
        <Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
          <Setter Property="Foreground" Value="Red" />
        </Style>
      </ResourceDictionary>

    </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
</Application.Resources>

This should give ALL your textboxes red foreground color without having to explicitly specify that on each window and user control.

like image 70
Oskar Avatar answered Nov 15 '22 05:11

Oskar


I had the same problem and tried Oskar's approach. Though, it caused some strange behaviour. Particularly, the styles did not apply to some controls, while applying to other controls of the same type. And I could not find any major differences between these controls.

I continued searching for the solution and I found one here: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/91718816-8674-4ad8-a3c8-ae283bebe224/

It is still not perfect and clear, but it works, at least for me.

In brief, you can get the idea from the following code:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="/PresentationFramework.Aero, Version=3.0.0.0,
        Culture=neutral, PublicKeyToken=31bf3856ad364e35,
        ProcessorArchitecture=MSIL;component/themes/Aero.NormalColor.xaml" />
                </ResourceDictionary.MergedDictionaries>
                <Style x:Key="ExtendedTextBoxStyle" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
                    <Setter Property="Foreground" Value="Red" />
                </Style>
            </ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>
        <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource ExtendedTextBoxStyle}" />
    </ResourceDictionary>
</Application.Resources>

For maintainability and readability these nested ResourceDictionary objects could go to separate XAML files.

like image 44
Alex Che Avatar answered Nov 15 '22 06:11

Alex Che