-->

How to correctly set an WPF EventTrigger in style?

2019-08-01 19:09发布

问题:

I have a WPF style that is a border. It is used for a button.

<Style x:Key="RoundCorner" TargetType="{x:Type Button}">
    <Setter Property="ClickMode" Value="Press"/>
    <EventSetter Event="PreviewMouseUp" Handler="RegularButtonRelease"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid x:Name="grid">
                    <Border x:Name="border" CornerRadius="2" BorderBrush="#FF444444" BorderThickness="1">
                        <Border.Background>
                            <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1.2" >
                                <GradientStop Color="#ffaaaaaa" Offset="0" />
                                <GradientStop Color="White" Offset="1" />
                            </LinearGradientBrush>                             
                        </Border.Background>
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsPressed" Value="True">
                        <!--some style -->
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="True">
                        <!--some style -->                                
                    </Trigger>
                    <EventTrigger RoutedEvent="PreviewMouseLeftButtonUp">
                        <BeginStoryboard>
                            <Storyboard Duration="0:0:2" AutoReverse="False">
                                <ColorAnimation 
                                    Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" 
                                    FillBehavior="Stop" To="Tomato"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

I want to set the border background color to a different one for a given time, when I release the mouse click on the button. (e.g. the button is black when pressed, and when I release, it changes to red, then changes back to white)

Using the above code, I can see the button color keep changing after I release mouse button, and my event handler RegularButtonRelease is fired continuously too. Soon the appplication hangs, and gives me a System.StackOverflowException exception.

If I take away the EventTrigger in style, my applications perform correctly, so my EventTrigger must be wrong.

My question is, how could I correctly set a background color change at mouse button up (using the EventTrigger or something else)?

UPDATE:

I try to set the border and background at the same time using:

<ColorAnimation 
    Duration="0:0:0.8" 
    Storyboard.TargetName="border" 
    Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" 
    To="Red"/>
<ColorAnimation 
    Duration="0:0:0.8" 
    Storyboard.TargetName="border" 
    Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" 
    To="Red"/>

This time the border line is changing to red, works like a charm. But the background still sits there, no any changes.

How can I correctly change my background?

回答1:

First, your mistakes : You are trying to change Color of Background which is not possible as it is set to LinearGradientBrush, and secondly you have not set Storyboard.TargetName at all.

I have done some changes, first : Assign x:Name to second GradientStop, and then use this x:Name as Storyboard.TargetName="C2" in animation.

<Style x:Key="RoundCorner" TargetType="{x:Type Button}">
        <Setter Property="ClickMode" Value="Press"/>
        <EventSetter Event="PreviewMouseUp" Handler="RegularButtonRelease"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid x:Name="grid">
                        <Border x:Name="border" CornerRadius="2" BorderBrush="#FF444444" BorderThickness="1">
                            <Border.Background>
                                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1.2" >
                                    <GradientStop Color="#ffaaaaaa" Offset="0" />
                                    <GradientStop x:Name="C2" Color="White" Offset="1" />
                                </LinearGradientBrush>
                            </Border.Background>
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsPressed" Value="True">
                            <!--some style -->
                        </Trigger>
                        <Trigger Property="IsMouseOver" Value="True">
                            <!--some style -->
                        </Trigger>
                        <EventTrigger RoutedEvent="PreviewMouseLeftButtonUp">
                            <BeginStoryboard>
                                <Storyboard Duration="0:0:1" AutoReverse="False">
                                    <ColorAnimation Storyboard.TargetName="C2"
                                        Storyboard.TargetProperty="Color" 
                                        FillBehavior="Stop" To="Red"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>


回答2:

Or try this example :

<ControlTemplate.Triggers>
            <Trigger Property="IsPressed" Value="True">
              <Setter Property="Background" TargetName="Background" Value="Red"/>
            </Trigger>
        </ControlTemplate.Triggers>

For reference:

Change color of Button when Mouse is over

How do you change Background for a Button MouseOver in WPF?

Coming to the System.StackOverflowException part, according to MSDN you can get StackOverflowExceptions by creating too many large objects on the stack, it usually happens because your code has got into a state where it is calling the same chain of functions over and over again. Something like recursion.