Home > Software engineering >  How to change image on mouseover on a button with stackpanel having an Image and a Textblock XAML
How to change image on mouseover on a button with stackpanel having an Image and a Textblock XAML

Time:12-10

I'm kinda new to WPF/XAML

I have this Button that holds a stack panel which is having an Image and a Textbox Control to it.

I have styled the button in a StaticResource

How can I achieve an image change on MouseOver?

I have accomplished changing the Background color, and the Foreground color (text) to change on mouseover, but I can't get the image change to work

This is my Button:

                <Button Style="{StaticResource mainMenuHomeBtn}">
                    <StackPanel
                        Orientation="Horizontal"
                        HorizontalAlignment="Left">
                        <Image Name="hjemImage" Margin="5" Height="30" Source="/Images/fal-home-lg-alt.png"/>
                        <TextBlock Margin="10" VerticalAlignment="Center" Text="Hjem"/>
                    </StackPanel>
                </Button>

And this is my Button Styling:

        <Style x:Key="mainMenuHomeBtn" TargetType="{x:Type Button}">
            <Setter Property="Width" Value="auto"/>
            <Setter Property="Height" Value="auto"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="HorizontalContentAlignment" Value="Left"/>
            <Setter Property="Padding" Value="-2"/>
            <Setter Property="Foreground" Value="#e3e3e3"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border Background="{TemplateBinding Background}" BorderBrush="#cccccc" BorderThickness="0">
                            <ContentPresenter HorizontalAlignment="Left"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Foreground" Value="#696969"/>
                    <Setter Property="Background" Value="#d9d9d9"/>
                </Trigger>
                <Trigger Property="IsPressed" Value="True">
                    <Setter Property="Background" Value="#e3e3e3"/>
                </Trigger>
            </Style.Triggers>
        </Style>

CodePudding user response:

Your Style/ControlTemplate doesn't know anything about the StackPanel that happens to be in the element that is currently set as the Content of the Button element that the Style is currently applied to.

You could move the contents to the template and use a trigger so change the Source of the Image element in the template:

<Style x:Key="mainMenuHomeBtn" TargetType="{x:Type Button}">
    <Setter Property="Width" Value="auto"/>
    <Setter Property="Height" Value="auto"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="HorizontalContentAlignment" Value="Left"/>
    <Setter Property="Padding" Value="-2"/>
    <Setter Property="Foreground" Value="#e3e3e3"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border Background="{TemplateBinding Background}" BorderBrush="#cccccc" BorderThickness="0">
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
                        <Image Name="hjemImage" Margin="5" Height="30" Source="/Images/fal-home-lg-alt.png"/>
                        <TextBlock Margin="10" VerticalAlignment="Center" Text="Hjem"/>
                    </StackPanel>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="hjemImage" Property="Source" Value="pic.png" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Foreground" Value="#696969"/>
            <Setter Property="Background" Value="#d9d9d9"/>
        </Trigger>
        <Trigger Property="IsPressed" Value="True">
            <Setter Property="Background" Value="#e3e3e3"/>
        </Trigger>
    </Style.Triggers>
</Style>

Then there is no point of setting the Content property since there is no ContentPresenter in the Style:

<Button Style="{StaticResource mainMenuHomeBtn}" />

The other option is to keep your Style as-is and add a DataTrigger that binds to the IsMouseOver property of the Button to an element in the content:

<Button Style="{StaticResource mainMenuHomeBtn}">
    <StackPanel Orientation="Horizontal"
                HorizontalAlignment="Left">
        <Image Name="hjemImage" Margin="5" Height="30">
            <Image.Style>
                <Style TargetType="Image">
                    <Setter Property="Source" Value="/Images/fal-home-lg-alt.png" />
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType=Button}}"
                                     Value="True">
                            <Setter Property="Source" Value="pic.png" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Image.Style>
        </Image>
        <TextBlock Margin="10" VerticalAlignment="Center" Text="Hjem"/>
    </StackPanel>
</Button>
  • Related