3
votes

I want my application to animate an ellipse to a new position everytime a certain event happens. For testing purposes I made a button that changes a viewmodel property and this property is bound to a datatrigger that fires the animation, but later on I want the viewmodel to trigger it based on other events I haven't implemented yet - that's why I can't use the eventtrigger being bound to that button directly in the view, I need the viewmodel. Because the ellipse is supposed to be moved by the animation to a new position everytime it gets fired, I need to bind the TO-Property of the DoubleAnimation to a value in the viewmodel. This works fine when I use a normal eventtrigger, but using the datatrigger crashes the XamlParser with that binding. I don't get any specific error except for an XAMLParseException, however, if I change the binding to a fixed value, for example 5, it'll work fine.

Here's the xaml:

<Window x:Class="AnimationExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:AnimationExample"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">

    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>

    <Canvas Name="CanvasWrapper" Width="525" Height="350">
        <Button Content="Next Animation" Command="{Binding NextAnimation}"/>
            <Ellipse Fill="Red" Width="60" Height="60" Canvas.Left="60" Canvas.Top="60">
            <Ellipse.Style>
                <Style>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding CanAnimate}" Value="True" >
                            <DataTrigger.EnterActions>
                                <BeginStoryboard >
                                    <Storyboard>
                                        <!-- Works fine without the binding -->
                                        <DoubleAnimation
                                            Storyboard.TargetProperty="(Canvas.Left)"
                                            Duration="0:0:10" To="{Binding NextPosX}" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </DataTrigger.EnterActions>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Ellipse.Style>
        </Ellipse>
    </Canvas>
</Window>

I believe that the parser is unable to find the correct path to the binding, even though the code completion shows it. Is there even a way I can get the correct path to the binding?

1

1 Answers

2
votes

Read the section Data Binding and Animating Animations : basically animations are created frozen (i.e. all of its properties are read-only and hence can't be modified), the animation has to be recreated to reflect on property changed notifications.

Have a look at this blog entry and at this SOF question.

Update based on your comment:

First why DataTrigger and StoryBoard binding does not work?

The answer is provided by Storyboards Overview as follows:

You can't use dynamic resource references or data binding expressions to set Storyboard or animation property values. That's because everything inside a Style must be thread-safe, and the timing system must Freeze Storyboard objects to make them thread-safe. A Storyboard cannot be frozen if it or its child timelines contain dynamic resource references or data binding expressions. For more information about freezing and other Freezable features, see the Freezable Objects Overview.

Why binding work with EventTrigger but not with DataTrigger?

Again from the same source:

Animations applied by property Trigger objects behave in a more complex fashion than EventTrigger animations or animations started using Storyboard methods. They "handoff" with animations defined by other Trigger objects, but compose with EventTrigger and method-triggered animations.

I will assume that what they mean is that with EventTriggers the StoryBoard is recreated at the time of the event, but this is not the case with DataTriggers - "handoff" seems to imply Sharing of the StoryBoard. I will create a SO question to verify what is meant by this (question created here: Storyboard: EventTrigger vs DataTrigger ).