简体   繁体   中英

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?

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>

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM