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!
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…
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:
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:
When the user clicks on a little circle beneath the ItemsControl to select a page, this method in the PageOfKittyKatsViewModel class executes:
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.
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.