1

The following code effectively displays an image as the background for a button and changes the image on a isMouseOver event. What I would like to be able to do is use the same style for multiple buttons but be able to change the background image (ImageBrush) individually for each button since each one will use a different image.

Is it possible to use the same Resource Style in multiple buttons and change the background image individually on an IsMouseOver or do I need separate styles for each one?

Style

<Window.Resources>
    <Style x:Key="MainMenuButtonTemplate" TargetType="{x:Type Button}">
        <Style.Setters>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">

                        <Border x:Name="button" CornerRadius="12" 
                                Background="{TemplateBinding Background}"
                                Width="{TemplateBinding Width}"
                                Height="{TemplateBinding Height}">

                            <TextBlock  Text="{TemplateBinding Button.Content}" 
                                        HorizontalAlignment="Center" 
                                        VerticalAlignment="Center"/>
                        </Border>

                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">

                                <Setter TargetName="button"  Property="Background">
                                    <Setter.Value>
                                        <ImageBrush ImageSource="/MyProject;component/Design/Images/my-image.png" Stretch="None"/>
                                    </Setter.Value>
                                </Setter>
                            </Trigger>

                            <Trigger Property="IsPressed" Value="True">
                                <Setter TargetName="button"  Property="Background">
                                    <Setter.Value>
                                        <SolidColorBrush Color="{StaticResource MyCustomColor}"/>
                                    </Setter.Value>
                                </Setter>
                            </Trigger>

                            <Trigger Property="IsFocused" Value="True">
                            </Trigger>

                            <Trigger Property="IsEnabled" Value="False">
                                <Setter TargetName="button" Property="Opacity" Value="0.7" />
                                <Setter Property="Foreground" Value="Gray" />
                            </Trigger>
                        </ControlTemplate.Triggers>

                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style.Setters>
    </Style>
</Window.Resources>

Use

<Button x:Name="MyButton"
    Style="{StaticResource MainMenuButtonTemplate}" 
    Margin="0,50,0,0" 
    Width="auto" 
    Height="60" 
    Command="{Binding FindrViewCommand}" 
    BorderBrush="{x:Null}" 
    Foreground="White" >
    <Button.Background>
        <ImageBrush ImageSource="Design/Images/my-hover-image.png" Stretch="None"/>
    </Button.Background>
</Button>
Community
  • 1
  • 1
fs_tigre
  • 10,650
  • 13
  • 73
  • 146
  • 1
    Another answer written by me, which shows attached DP using for IsMouseOver trigger: https://stackoverflow.com/a/45909174/1506454 – ASh Jun 09 '18 at 08:22

1 Answers1

3

The Button class only contains one Dependency Property (DP) for Background, there is no DP for IsMouseOver background.

You have multiple choices, here's a few :

1) Create an Attached Property named IsMouseOverBackground of type Brush and bind to it in your Style.

C#

namespace WpfApp1
{
    public class ButtonHelper
    {
        public static readonly DependencyProperty IsMouseOverBackgroundProperty =
            DependencyProperty.RegisterAttached("IsMouseOverBackground", typeof(Brush), typeof(ButtonHelper), new PropertyMetadata(null));

        public static Brush GetIsMouseOverBackground(DependencyObject obj)
        {
            return (Brush)obj.GetValue(IsMouseOverBackgroundProperty);
        }

        public static void SetIsMouseOverBackground(DependencyObject obj, Brush value)
        {
            obj.SetValue(IsMouseOverBackgroundProperty, value);
        }
    }
}

XAML

<!-- ... -->
<Trigger Property="IsMouseOver" Value="True">
    <Setter TargetName="button" Property="Background" Value="{Binding (local:ButtonHelper.IsMouseOverBackground), RelativeSource={RelativeSource TemplatedParent}}" />
</Trigger>
<!-- ... -->

Note the use of parentheses in the Binding, that is needed when binding to an Attached Property.

2) Create a IsMouseOverButton class that inherits from Button, add a DP called IsMouseOverBackground of type Brush and bind to it in your Style.

C#

namespace WpfApp1
{
    public class IsMouseOverButton : Button
    {
        public static readonly DependencyProperty IsMouseOverBackgroundProperty =
            DependencyProperty.Register("IsMouseOverBackground", typeof(Brush), typeof(IsMouseOverButton), new PropertyMetadata(null));

        public Brush IsMouseOverBackground
        {
            get { return (Brush)GetValue(IsMouseOverBackgroundProperty); }
            set { SetValue(IsMouseOverBackgroundProperty, value); }
        }
    }
}

XAML

<Style x:Key="MainMenuButtonTemplate" TargetType="{x:Type local:IsMouseOverButton}">
    <Style.Setters>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:IsMouseOverButton}">

                    <Border x:Name="button" CornerRadius="12" 
                            Background="{TemplateBinding Background}"
                            Width="{TemplateBinding Width}"
                            Height="{TemplateBinding Height}">

                        <TextBlock  Text="{TemplateBinding Button.Content}" 
                                    HorizontalAlignment="Center" 
                                    VerticalAlignment="Center"/>
                    </Border>

                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="button" Property="Background" Value="{Binding IsMouseOverBackground, RelativeSource={RelativeSource TemplatedParent}}" />
                    </Trigger>
<!-- ... -->

<local:IsMouseOverButton x:Name="MyButton"
                         Style="{StaticResource MainMenuButtonTemplate}" 
                         Margin="0,50,0,0" 
                         Width="auto" 
                         Height="60" 
                         Command="{Binding FindrViewCommand}"
                         BorderBrush="{x:Null}" 
                         Foreground="White">
    <local:IsMouseOverButton.Background>
        <ImageBrush ImageSource="https://dummyimage.com/600x400/000/fff" Stretch="None"/>
    </local:IsMouseOverButton.Background>
    <local:IsMouseOverButton.IsMouseOverBackground>
        <ImageBrush ImageSource="https://dummyimage.com/600x401/000/fff" Stretch="None"/>
    </local:IsMouseOverButton.IsMouseOverBackground>
</local:IsMouseOverButton>

3) Use the Tag property of your Button to store the IsMouseOver background and bind to it in your Style. I'm not a fan of using Tag property as it's unclear why Tag property is used when another developer reads your code.

Roger Leblanc
  • 1,543
  • 1
  • 10
  • 9
  • 2
    there is one more option: `{DynamicResource }` for IsMouseOverBackground (see my linked Possible Duplicate) – ASh Jun 09 '18 at 08:23