2
votes

Consider the following simple WPF form, we will try to animate border1's Height:

alt text

This is the XAML for border1:

<Border Margin="3" BorderBrush="Black" BorderThickness="1" Name="border1">
    <Border.Style>
        <Style>
            <Setter Property="Control.Height" Value="50" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding X}" Value="1">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Height" To="100" />
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
                <DataTrigger Binding="{Binding X}" Value="2">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Height" To="200" />
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
                <DataTrigger Binding="{Binding X}" Value="3">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Height" To="300" />
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Border.Style>
    <TextBlock Text="{Binding X}" />
</Border>

X is a normal DependencyProperty and buttons do their work without problem and TextBlock's content inside border1 shows the changed value.

Now the problem is Height can be only Increased! For example by pressing 1, Height increases to 100, pressing 3 increases it to 300 but pressing 2 does not change the height.

If I set the initial border1's height to, for example, 400, all buttons can decrease it to 100, 200 or 300 but after this stage no animation can decrease border's height.

Am I missing some obvious point regarding WPF animation?

2
If you reverse the order of your three DataTriggers (3,2,1 instead of 1,2,3)... do you get the reverse effect (you can only decrease instead of increase)? - Scott
You are just setting the Height not Increasing the Height. Are you trying to achieve a Zooming like effect? - Prince Ashitaka
@Avatar - no, he means to actually set the Height. @Scott - that is the case. - Wonko the Sane
I've reproduced this, cuz its driving me nuts not being able to figure it out. It seems like the answer is right there, but... It does have to do with the DataTriggers, because setting a hard-coded value (say, 150) with another Button Click doesn't resize the Border either. - Wonko the Sane
Well... after a lot of research... I finally came up with a good solution. I've updated my answer to reflect this and attempt to explain what the issue is. MSDN hints at it... but doesn't exactly explain why DataTriggers seem to have this issue but EventTriggers do not. msdn.microsoft.com/en-us/library/aa970492.aspx - Scott

2 Answers

3
votes

Update

Part of the issue is the storyboard in the DataTrigger is not being stopped, so (the last DataTrigger defined) is always holding the Height's 'animated' value.

Adding a StopStoryboard in the exit action fixes part of it. You can now switch between all three heights again... but the animation always starts from the Height's base value (which is clearly not what you want). You want it to start from where it was last set at.

The following MSDN article explains the second issue pretty well: http://msdn.microsoft.com/en-us/library/aa970493.aspx

Good Solution-

<Border Margin="3" BorderBrush="Black" BorderThickness="1" Name="border1"> 
    <Border.Style> 
        <Style> 
            <Setter Property="Control.Height" Value="50" /> 
        </Style> 
    </Border.Style> 
    <TextBlock Text="{Binding X}" /> 
</Border> 

and

<StackPanel Orientation="Horizontal">
    <Button Content="1" Width="50">
        <Button.Triggers>
            <EventTrigger RoutedEvent="Button.Click">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetName="border1" Storyboard.TargetProperty="Height" To="100"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Button.Triggers>
    </Button>
    <Button Content="2" Width="50">
        <Button.Triggers>
            <EventTrigger RoutedEvent="Button.Click">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetName="border1" Storyboard.TargetProperty="Height" To="200"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Button.Triggers>
    </Button>
    <Button Content="3" Width="50">
        <Button.Triggers>
            <EventTrigger RoutedEvent="Button.Click">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetName="border1" Storyboard.TargetProperty="Height" To="300"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Button.Triggers>
    </Button>
</StackPanel>
2
votes

There must be a simpler way to do this, but I cannot recall if there is at the moment.

Otherwise this will work. You can set the ExitAction of your triggers to set back to the default value. Do this by using a DoubleAnimation with no To value.

i.e.,

<DataTrigger Binding="{Binding X}" Value="1">
    <DataTrigger.EnterActions>
        <BeginStoryboard>
            <Storyboard>
                <DoubleAnimation Storyboard.TargetProperty="Height" Duration="0:0:0.2" To="100" />
            </Storyboard>
        </BeginStoryboard>
    </DataTrigger.EnterActions>
    <DataTrigger.ExitActions>
        <BeginStoryboard>
            <Storyboard>
                <DoubleAnimation Storyboard.TargetProperty="Height" Duration="0:0:0.2" />
            </Storyboard>
        </BeginStoryboard>
    </DataTrigger.ExitActions>
</DataTrigger>