Search code examples
wpfwpf-style

Overriding a specific property in style


I have an application with toggle buttons that needs to change the background based on the checked state. This application also have some regular buttons, that share the same background as the toggle buttons. Also, they all have rounded corners.

So I came up with these styles:

<Style TargetType="Button" BasedOn="{StaticResource {x:Type Control}}" x:Key="OnButton">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Border CornerRadius="15" Background="{StaticResource GradientBrushOn}" BorderThickness="1" Padding="2">
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style TargetType="Button" BasedOn="{StaticResource OnButton}" x:Key="OffButton">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Border CornerRadius="15" Background="{StaticResource GradientBrushOff}" BorderThickness="1" Padding="2" x:Name="TheBorder">
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Long story short, I'm looking for a way to shorten the OffButton style so that it only changes the Background property of the OnButton style from GradientBrushOn to GradientBruthOff.

This is my first time working with WPF so I assume this should be a fairly basic thing, However I just couldn't find any way to do it, not even after spending 2 hours on google.


Solution

  • Use Button.Background property and in ControlTemplate use TemplateBinding

    <Style TargetType="Button" BasedOn="{StaticResource {x:Type Control}}" x:Key="OnButton">
        <Setter Property="Background" Value="{StaticResource GradientBrushOn}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border CornerRadius="15" Background="{TemplateBinding Background}" BorderThickness="1" Padding="2">
                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    
    <Style TargetType="Button" BasedOn="{StaticResource OnButton}" x:Key="OffButton">
        <Setter Property="Background" Value="{StaticResource GradientBrushOff}"/>
    </Style>
    

    this will also work if you do

    <Button Style="..." Background="Green"/>
    

    EDIT

    Since you have to change whole template normally in your ControlTemplate you would utilize as many built in properties of your control like Background, BorderBrush, BorderThickness, Padding, HorizontalContentAlignment, VerticalContentAlignment and so on so you can share template and only tweak things from Style for example

    <Style TargetType="Button" BasedOn="{StaticResource {x:Type Control}}" x:Key="OnButton">
       <Setter Property="Background" Value="{StaticResource GradientBrushOn}"/>
       <Setter Property="BorderThickness" Value="1"/>
       <Setter Property="Padding" Value="2"/>
       <Setter Property="HorizontalContentAlignment" Value="Center"/>
       <Setter Property="VerticalContentAlignment" Value="Center"/>
       <Setter Property="Template">
           <Setter.Value>
               <ControlTemplate TargetType="Button">
                   <Border CornerRadius="15" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Padding="{TemplateBinding Padding}">
                       <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                   </Border>
               </ControlTemplate>
           </Setter.Value>
       </Setter>
    </Style>