Search code examples
wpfstylesthemesskinbasedon

How to extend instead of overriding WPF Styles


I want to use custom theme in my application and as far as I know I can accomplish this by using resource dictionary and referencing it in App.xaml. Styles would override the defaults like this:

<Style TargetType="{x:Type Label">
    <Setter Property="Foreground" Value="Green" />
</Style>

Now as I guess the default Label style is overriden with same values but all my label fonts are green. The problem starts when I want to style one label somewhere again. When I want to change some other property in my Grid like this

<Grid.Resources>
    <Style TargetType="{x:Type Label">
        <Setter Property="FontSize" Value="28" />
    </Style>
</Grid.Resources>

All labels inside my grid are losing their foreground color and have default one again (didn't I override defaults in previous step?). After some tries I found out that to do this properly i have to add another property to Style declaration BasedOn={StaticResource {x:Type Label}}" and it works. This is kind of weird for me because now I will have to repeat same BasedOn code in whole app and this is not how styling works - this should be done automatically! For example in HTML + CSS styles are inherited and merged and in WPF they are replaced...

Notice that when I don't use any styles controls still get their look from somehwere (System Themes?). How can I tell them to look for defaults somewhere else so without any additional code on styles they will think that they should be green by default?

Is there any way I can automate setting BasedOn property? Or maybe there is a better to do this overally?


Solution

  • I had the same problem. I used Zack's answer and improved it like following so if you don't specify a style the overridden default is still taken in account. It's basically what you would have done but just once in the ResourceDictionary.

    <Window x:Class="TestWpf.RandomStuffWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Random Stuff Window">
      <Window.Resources>
        <ResourceDictionary>
          <!-- Default Label style definition -->
          <Style TargetType="{x:Type Label}">
            <Setter Property="Foreground" Value="Green" />
          </Style>
          <!-- Extending default style -->
          <Style TargetType="{x:Type Label}" 
                 x:Key="LargeGreenForegroundLabel" 
                 BasedOn="{StaticResource {x:Type Label}}">
            <Setter Property="FontSize" Value="28" />
          </Style>
        </ResourceDictionary>
      </Window.Resources>
      <StackPanel>
        <Button Click="Button_Click">Click</Button>
        <Label Content="GreenForegroundLabel" /> <!-- Uses default style -->
        <Label Style="{StaticResource LargeGreenForegroundLabel}" 
               Content="LargeGreenForegroundLabel" />
      </StackPanel>
    </Window>