Search code examples
c#wpfxamlmouseovercontroltemplate

Can't change background button property anymore if mouseOver have been overridden


In the image below, I have 3 buttons (UserControls) on which I changed the default mouseOver effect. In the picture, I'm currently hovering the button 1.

enter image description here

Here is the code I used:

<Style x:Key="ButtonMouseOver" TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border>
                    <Border.Style>
                        <Style TargetType="{x:Type Border}">
                             <Style.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Background" Value="#404040"/>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </Border.Style>
                    <Grid Background="Transparent">
                        <ContentPresenter></ContentPresenter>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

My user control buttons:

<Button HorizontalContentAlignment="Stretch" Style="{StaticResource ButtonMouseOver}" VerticalContentAlignment="Stretch" Background="{Binding ButtonColor}" BorderThickness="0">

But now, I can't change the color of my buttons anymore with the Background property. Any ideas why?


Solution

  • When you override a ControlTemplate you have to be careful to use TemplateBinding to bind to properties of the templated target control, otherwise they take their default value or the explicit value that you have assigned in the template, but they cannot be overriden directly or in a Style.

    In your example, you have to bind the Background of the Border with a TemplateBinding so that it uses the value from the Background property of the templated Button. You should do that for all properties of Button to enable different styles.

    <ControlTemplate TargetType="{x:Type Button}">
       <Border Background="{TemplateBinding Background}">
       <!-- ...other definitions -->
    </ControlTemplate>
    

    From the documentation of TemplateBinding:

    Links the value of a property in a control template to be the value of another property on the templated control.

    Here is a simplified version of your control template with a template binding for background, as well as a default value defined in its style, that can be overriden in another style or directly on the button.

    <Style x:Key="ButtonMouseOver" TargetType="{x:Type Button}">
       <Setter Property="Background"
               Value="#777777"/>
       <Setter Property="Template">
          <Setter.Value>
             <ControlTemplate TargetType="{x:Type Button}">
                <Border x:Name="MyBorder"
                        Background="{TemplateBinding Background}">
                   <ContentPresenter HorizontalAlignment="Center"
                                     VerticalAlignment="Center"/>
                </Border>
                <ControlTemplate.Triggers>
                   <Trigger Property="IsMouseOver"
                            Value="True">
                      <Setter TargetName="MyBorder"
                              Property="Background"
                              Value="#404040"/>
                   </Trigger>
                </ControlTemplate.Triggers>
             </ControlTemplate>
          </Setter.Value>
       </Setter>
    </Style>