user0103
user0103

Reputation: 1272

Change button image on mouse hover

I have following XAML code:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="480" Width="640" ResizeMode="NoResize">
    <Window.Background>
        <SolidColorBrush x:Name="WindowBrush" Color="#202020" />
    </Window.Background>
    <Window.Resources>
        <Style TargetType="Button">
            <Setter Property="BorderBrush" Value="Transparent" />
            <Setter Property="Background">
                <Setter.Value>
                    <ImageBrush ImageSource="Resources/button.png"/>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background">
                        <Setter.Value>
                            <ImageBrush ImageSource="Resources/button-hover.png"/>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="285*"/>
            <ColumnDefinition Width="349*"/>
        </Grid.ColumnDefinitions>
        <Button Content="Button" HorizontalAlignment="Left" Height="28" Margin="21,20,0,0" VerticalAlignment="Top" Width="79" BorderThickness="1"/>
    </Grid>
</Window>

And of course, I have two images im my project — button.png and button-hover.png. But when cursor is over my button it apply default Windows style, not my button-hover.png image. Where is my mistake? Thank you.

Upvotes: 1

Views: 1184

Answers (1)

Linga
Linga

Reputation: 10573

This is an example style:

<Style TargetType="Button">
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="Button">
            <Grid>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal"/>
                        <VisualState x:Name="Disabled"/>
                        <VisualState x:Name="MouseOver">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetName="mouseOverBackgroundImage" Storyboard.TargetProperty="Opacity" Duration="0:0:0.1" To="1"/>
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Pressed">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetName="pressedBackgroundImage" Storyboard.TargetProperty="Opacity" Duration="0:0:0.1" To="1"/>
                            </Storyboard>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <Image Name="normalBackgroundImage" Source="{TemplateBinding local:BackgroundImages.NormalBackgroundImage}"/>
                <Image Name="mouseOverBackgroundImage" Source="{TemplateBinding local:BackgroundImages.MouseOverBackgroundImage}" Opacity="0"/>
                <Image Name="pressedBackgroundImage" Source="{TemplateBinding local:BackgroundImages.PressedBackgroundImage}" Opacity="0"/>
                <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </Grid>
        </ControlTemplate>
    </Setter.Value>
</Setter>

used in a Button with the attached properties set:

<Button local:BackgroundImages.NormalBackgroundImage="C:\Users\Public\Pictures\Sample Pictures\Tulips.jpg"
    local:BackgroundImages.MouseOverBackgroundImage="C:\Users\Public\Pictures\Sample Pictures\Desert.jpg"
    local:BackgroundImages.PressedBackgroundImage="C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg"
    Content="Hello"/>

And finally the definition of those attached properties:

public static class BackgroundImages
{
public static readonly DependencyProperty NormalBackgroundImageProperty =
    DependencyProperty.RegisterAttached("NormalBackgroundImage", typeof(ImageSource), typeof(BackgroundImages));

public static readonly DependencyProperty MouseOverBackgroundImageProperty =
    DependencyProperty.RegisterAttached("MouseOverBackgroundImage", typeof(ImageSource), typeof(BackgroundImages));

public static readonly DependencyProperty PressedBackgroundImageProperty =
    DependencyProperty.RegisterAttached("PressedBackgroundImage", typeof(ImageSource), typeof(BackgroundImages));

public static ImageSource GetNormalBackgroundImage(DependencyObject obj)
{
    return (ImageSource)obj.GetValue(NormalBackgroundImageProperty);
}

public static void SetNormalBackgroundImage(DependencyObject obj, ImageSource value)
{
    obj.SetValue(NormalBackgroundImageProperty, value);
}

public static ImageSource GetMouseOverBackgroundImage(DependencyObject obj)
{
    return (ImageSource)obj.GetValue(MouseOverBackgroundImageProperty);
}

public static void SetMouseOverBackgroundImage(DependencyObject obj, ImageSource value)
{
    obj.SetValue(MouseOverBackgroundImageProperty, value);
}

public static ImageSource GetPressedBackgroundImage(DependencyObject obj)
{
    return (ImageSource)obj.GetValue(PressedBackgroundImageProperty);
}

public static void SetPressedBackgroundImage(DependencyObject obj, ImageSource value)
{
    obj.SetValue(PressedBackgroundImageProperty, value);
}
}

For triggers, Try something like this. I'm not sure of this: (just add the image to an /Images folder in the project)

<ControlTemplate TargetType="Button">
<Border Name="border" BorderThickness="0" 
            Background="Transparent">
      <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
    <Trigger Property="IsMouseOver" Value="True">
        <Setter Property="Background">
           <Setter.Value>
               <ImageBrush ImageSource="/MyProjectName;component/Images/MyImage.jpg" />
           </Setter.Value>
        </Setter>
    </Trigger>
</ControlTemplate.Triggers>

You could define attached properties for the background images for states Normal, MouseOver and Pressed (and maybe more). You would use these attached properties for the Sourceproperty of separate Image controls in a control template and modify e.g. the Image's Opacity when the VisualState changes.

Upvotes: 3

Related Questions