Daniel Häfele
Daniel Häfele

Reputation: 872

Button Template - IsMouseOver stops working after IsPressed is executed

I have a strange problem and I hope you can help me.

I created a style for a button and added some triggers to the template. One for IsMouseOver and one for IsPressed.

Both triggers have an EnterAction and an ExitAction animating the background-color of the template.

When I just hover over the button I can see the color changing, but after I clicked on the button the hover trigger stops working.

Here's a example code:

<Button Margin="142,130,214,138" Content="Hi Mum!">

    <Button.Resources>
        <Color x:Key="backgroundColor" A="255" R="52" G="152" B="219" />
        <Color x:Key="hoverBackgroundColor" A="255" R="62" G="182" B="255" />
        <Color x:Key="pressedBackgroundColor" A="255" R="42" G="122" B="175" />
    </Button.Resources>

    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">

                        <Border BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                CornerRadius="6">
                            <Border.Background>
                                <SolidColorBrush x:Name="backgroundBrush" Color="{StaticResource backgroundColor}" />
                            </Border.Background>

                            <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" 
                                                Content="{TemplateBinding Content}" 
                                                ContentStringFormat="{TemplateBinding ContentStringFormat}" 
                                                Focusable="False" 
                                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                                Margin="{TemplateBinding Padding}" 
                                                RecognizesAccessKey="True" 
                                                SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                        </Border>

                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Trigger.EnterActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ColorAnimation Storyboard.TargetName="backgroundBrush" Storyboard.TargetProperty="Color" To="{StaticResource hoverBackgroundColor}" Duration="0:0:0.2" />
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.EnterActions>

                                <Trigger.ExitActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ColorAnimation Storyboard.TargetName="backgroundBrush" Storyboard.TargetProperty="Color" To="{StaticResource backgroundColor}" Duration="0:0:0.2" />
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.ExitActions>
                            </Trigger>

                            <Trigger Property="IsPressed" Value="True">
                                <Trigger.EnterActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ColorAnimation Storyboard.TargetName="backgroundBrush" Storyboard.TargetProperty="Color" To="{StaticResource pressedBackgroundColor}" Duration="0:0:0.2" />
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.EnterActions>

                                <Trigger.ExitActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ColorAnimation Storyboard.TargetName="backgroundBrush" Storyboard.TargetProperty="Color" To="{StaticResource backgroundColor}" Duration="0:0:0.2" />
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.ExitActions>
                            </Trigger>
                        </ControlTemplate.Triggers>

                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Button.Style>
</Button>

Upvotes: 1

Views: 1564

Answers (2)

franssu
franssu

Reputation: 2430

Looks like last trigger wins (try changing the order of your triggers, IsPressed first and IsMouseOver second and you'll see).

You really should use the VisualStateManager for this kind of stuff.

See the default's button template at the msdn for how to use the VSM.

http://msdn.microsoft.com/en-us/library/cc278069(v=vs.95).aspx

Edit for Sheridan : it works like a charm :

<Window.Resources>
        <Color x:Key="OverColor">Blue</Color>
        <Color x:Key="PressedColor">Green</Color>
    </Window.Resources>
    <Grid>
        <Button Content="Hi sheridan!" HorizontalAlignment="Center" VerticalAlignment="Center">
            <Button.Style>
                <Style TargetType="{x:Type Button}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type Button}">
                                <Border Background="LightBlue">
                                    <VisualStateManager.VisualStateGroups>
                                        <VisualStateGroup x:Name="CommonStates">
                                            <VisualStateGroup.Transitions>
                                                <VisualTransition GeneratedDuration="0:0:0.2"/>
                                            </VisualStateGroup.Transitions>
                                            <VisualState x:Name="Normal"/>
                                            <VisualState x:Name="Pressed">
                                                <Storyboard>
                                                    <ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)" 
                                                                    To="{StaticResource PressedColor}"/>
                                                </Storyboard>
                                            </VisualState>
                                            <VisualState x:Name="MouseOver">
                                                <Storyboard>
                                                <ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)" 
                                                                To="{StaticResource OverColor}"/>
                                                </Storyboard>
                                            </VisualState>
                                        </VisualStateGroup>
                                    </VisualStateManager.VisualStateGroups>

                                    <ContentPresenter Content="{TemplateBinding Content}"/>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </Button.Style>
        </Button>
    </Grid>

Upvotes: 2

Sheridan
Sheridan

Reputation: 69959

There are three parts to this solution:

  1. Name your IsMouseOver BeginStoryBoard objects.
  2. Use those names in two StopStoryBoard objects in the IsPressed Trigger.EnterActions.
  3. Reverse the order of your Trigger objects:

You should end up with something like this:

<Trigger Property="IsPressed" Value="True">
    <Trigger.EnterActions>
        <StopStoryboard BeginStoryboardName="MouseOverStoryBoard" />
        <StopStoryboard BeginStoryboardName="MouseOverStoryBoard2" />
        <BeginStoryboard>
            <Storyboard>
                <ColorAnimation Storyboard.TargetName="backgroundBrush" Storyboard.TargetProperty="Color" To="{StaticResource pressedBackgroundColor}" Duration="0:0:0.2" />
            </Storyboard>
        </BeginStoryboard>
    </Trigger.EnterActions>
    <Trigger.ExitActions>
        <BeginStoryboard>
            <Storyboard>
                <ColorAnimation Storyboard.TargetName="backgroundBrush" Storyboard.TargetProperty="Color" To="{StaticResource backgroundColor}" Duration="0:0:0.2" />
            </Storyboard>
        </BeginStoryboard>
    </Trigger.ExitActions>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
    <Trigger.EnterActions>
        <BeginStoryboard Name="MouseOverStoryBoard">
            <Storyboard>
                <ColorAnimation Storyboard.TargetName="backgroundBrush" Storyboard.TargetProperty="Color" To="{StaticResource hoverBackgroundColor}" Duration="0:0:0.2" />
            </Storyboard>
        </BeginStoryboard>
    </Trigger.EnterActions>
    <Trigger.ExitActions>
        <BeginStoryboard Name="MouseOverStoryBoard2">
            <Storyboard>
                <ColorAnimation Storyboard.TargetName="backgroundBrush" Storyboard.TargetProperty="Color" To="{StaticResource backgroundColor}" Duration="0:0:0.2" />
            </Storyboard>
        </BeginStoryboard>
    </Trigger.ExitActions>
</Trigger>

Actually, I think that you might be able to do without the second StopStoryboard, but having them both won't hurt.

Upvotes: 1

Related Questions