user969153
user969153

Reputation: 566

Change MVVM property from storyboard in XAML, after animation completes

I have different user controls defined as ItemSource DataTemplates for ListView, all sharing one ViewModel:

<UserControl>
  <Grid>
    <Style>
      <Style.Triggers>
        <DataTrigger Binding="{Binding MyAwesomeProperty}" Value="True">
          <DataTrigger.EnterActions>
            <BeginStoryboard>
              <Storyboard>
                <DoubleAnimation>
                 some awesome animation
                </DoubleAnimation>
              </Storyboard>
            </BeginStoryboard>
          </DataTrigger.EnterActions>
        </DataTrigger>
    </Style.Triggers>
</Style>
public class AwesomeViewModel : ViewModelBase
{
    private bool myAwesomeProperty= false;
    public bool MyAwesomeProperty
    {
        get { return myAwesomeProperty; }

        set
        {
            if (myAwesomeProperty!= value)
            {
                myAwesomeProperty= value;
                RaisePropertyChanged(() => MyAwesomeProperty);
            }
        }
    }
}

Now, I want to start animation when MyAwesomeProperty changes to true. This is accomplished by DataTrigger. However, once animation is completed, I want to set the value of the MyAwesomeProperty back to false.

As this logic is shared by multiple UserControls having the same ViewModel, I want pure MVVM solution, without Animation.Completed callbacks in the code-behind. Is this possible?

Upvotes: 0

Views: 1553

Answers (3)

kkyr
kkyr

Reputation: 3845

Here's a solution using Blend's interactivity library

First, right click References in your project, click Add Reference and under Framework add Microsoft.Expressions.Interaction and System.Windows.Interactivity.

After, add the following references to the top of your XAML file:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

Then you can do the following:

<Grid>
    <i:Interaction.Triggers>
        <ei:DataTrigger Binding="{Binding MyAwesomeProperty}" Value="True">
            <ei:ControlStoryboardAction Storyboard="{StaticResource YourAwesomeStoryboard}" ControlStoryboardOption="Play"/>
            <ei:ChangePropertyAction PropertyName="{Binding MyAwesomeProperty}" Value="False"/>
        </ei:DataTrigger>
    </i:Interaction.Triggers>
</Grid>

Upvotes: 1

kkyr
kkyr

Reputation: 3845

One immediate solution I can see to this is by initiating the storyboard in code behind and subscribe to the storyboard completed event. You can start a storyboard in code like this:

Storyboard storyBoard = (Storyboard)this.Resources["YourStoryBoard"];
storyBoard.Begin();

And then subscribe to its event

storyboard.Completed += storyboard_Completed;

void storyboard_Completed(object sender, System.EventArgs e)
{
    // your code here
}

Hope this was of help to you

Upvotes: 0

bkardol
bkardol

Reputation: 1268

Without code in your code-behind, you simply can't. I suggest you fire a Command on your ViewModel from code-behind to handle the logic. Like this you won't violate the MVVM pattern.

Upvotes: 0

Related Questions