Orchestrating Animated Transitions between View and ViewModel

Introduction

When working with the Model-View-ViewModel (MVVM) pattern, the data shown in a View is almost always transferred to it via data binding.  Changes made to properties on a ViewModel object immediately propagate to the binding targets in the View.  This is normally a good thing.  Sometimes, however, the immediacy of the propagation can be a problem.

Why would you want a new property value to not immediately show up in the UI?  Well, suppose you want to display an animated transition between the old value and the new value.  If the new value immediately shows up in the View, you won’t have a chance to animate “out” the old value before animating “in” the new value.   For example, suppose the property’s value is a page of data items to show in a list.  If we want to fade away the first page of items before fading in the new page of items, we need to start the fade-away animations before the new page of items is displayed.

This is the type of problem that the Visual State Manager (VSM) solves.  Since the VSM is not yet part of WPF proper (it won’t be until .NET 4.0), we cannot make use of it yet in production applications.  Also, the VSM is designed to be used inside of custom controls, so it is not exactly equivalent to what we are going to explore below.

The AnimatedTransition Class

I faced this exact problem many times while working on WPF and Silverlight applications.  After experimenting with several approaches to coordinating property changes with animated transitions, I started to understand the core problem more clearly.   Yesterday I listened to this incredible rendition of the Scherzo from Mendelssohn’s “A Midsummer’s Night Dream” and was hit by a flash of inspiration.  I realized a way to create a simple, type-safe, reusable way of having a ViewModel and View work together to create animated transitions between two property values.  The AnimatedTransition class was born!

AnimatedTransition

An instance of AnimatedTransition can be embedded in any ViewModel class.  The View(s) that need to perform transitions must access the AnimatedTransition object and hook one or more of its events in order to know when transitions should start.

The Demo App

In the demo app, which is available at the bottom of this post, there is an ItemsControl that displays four Hello Kitty images per “page,” as seen below…

kitty kats

When the user navigates to a different page, via the circles below, the old kitties fade away and then the new ones fade in.

We are not going to examine all of the classes involved in making this little app work.  If you want to get a high-level understanding of the ViewModel classes, click on this class diagram to view it at full size:

class diagram

The current page of kitties to show in the ItemsControl is contained in SelectedPage property of KittyKatTerraceViewModel.  Since we need to have a transition between the two values of that property, we use an AnimatedTransition to enable that.  Here is how KittyKatTerraceViewModel uses and exposes an AnimatedTransition:

animated transition creation

When the user clicks on a little circle beneath the ItemsControl to select a page, this method in the PageOfKittyKatsViewModel class executes:

starting a transition

All of the relevant logic in the KittyKatTerraceView control’s code-behind is listed below.  This shows how a View can consume and interact with an AnimatedTransition object.

transition usage

It’s important to note that you must attach a handler to the Completed event of the Storyboard that fades away the old items.  When the event is raised, the AnimatedTransition must be told to finish transitioning to the new value, and actually apply the value.  That is accomplished by calling the Finish() method.  Once the new value has been applied, the AfterApplyNewValue event is raised, at which time you can fade in the new items.

You can download the source code here.  Note: Be sure to change the file extension from .DOC to .ZIP and then decompress it.

10 Responses to Orchestrating Animated Transitions between View and ViewModel

  1. Nice work, as always😉

  2. Jason says:

    Very cool, thanks for sharing this

  3. Damien says:

    It looks great! Thanks for sharing it and also for making a useful demo application. I am always happy to find a nice MVVM example. I know it takes time to build and I do appreciate it.

  4. Jones says:

    Nice post…

  5. Ricardo says:

    Hi Josh, this is a good reusable way of doing it, I had the same problem too, what I did came from having used Prism, and how they connected the model and the view with an interface for the view. In this interface I place methods to control the animation of the view, the view model then calls this methods or listen to events to continue, is not actually re-usable but the advantages are:
    – The view contains the animations, not the view model.
    – The ViewModel does not need to access any internal objects of the View, in this case ItemsHost.
    – You can use different animations, not only property ones.

    Of course this approach has to be done in a case by case basis, I guess is more like a pattern.

    This a sample interface shared by the view and viewmodel:

    public interface ILogonView
    {
    void SetDataContext(object context);
    event EventHandler LogonAnimationCompleted;
    void StartLogonAnimation();
    void StartLogonFailedAnimation();
    }
    The ViewModel is in charge of the animations thru the methods and properties of the interface.

    Thanks for a great sample!

  6. Ben Reierson says:

    This has been on my mind a lot too and I’m glad to see others are thinking about it. I’m not entirely sure if this shouldn’t handled by the VSM. I tend to flip back and forth between the parent view dictating the transition, and the children handling their own transition.

    Your approach seems like a good start, but I don’t think it covers everything I’ve been struggling with.
    1. Sometimes the new item transition is going to depend on the state of the old items (their position, their size, etc). That can probably be solved by adding the old value as an argument to the ApplyNewValue events.
    2. What happens if the transition needs to include both the new value and the old value shown simultaneously? This could be as simple as a cross-fade, but I’ve run into more elaborate reasons for needing this.
    3. I love the RelayCommand and how well it reduces code in the view. I feel like we should be looking for a transition model that does better at this.

    I know you were trying to stick to production ready code, but what do you think of making use of behaviors for tranistions? Could a FadeIn/FadeOut behavior be attached to the items control or the item datatemplate and have it monitor for some kind of ITransition flag on any viewmodel it’s attached to? Then you’d just need a ViewModel that would flag items in a collection for removal before the behavior marks them as ready to remove completely.
    At first I thought about just using the VSM and changing to a IsTransitioning state or something on each control, but a behavior seems much more reusable.

  7. shiroica says:

    Hi, Josh. Nice article! your article is wonderful as always. Now, I’ a man who translated your article about attached behavior published in CodeProject. Thank you for giving permission at that time. May I translate this article to japanese and publicize on my blog as that article?

    Thanks alot.

  8. Josh Smith says:

    @Ben – Thanks for the brain food. 🙂

    @Shiroica – Yes, you can translate and republish this if you want to.

  9. […] M-V-VMパターンとアニメーションをどのようにして組み合わせるのかは、MVVMパターンを使う上で常に頭を悩ませる問題です。この問題に対して、Josh SmithさんがOrchestrating Animated Transitions between View and ViewModel >> Josh Smith on WPFというエントリでひとつの方法を示していたので、今回はこれを訳してみました。 […]

  10. […] Orchestrating Animated Transitions between View and ViewModel […]

%d bloggers like this: