(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Using Blend 4's new built-in TransitionEffects in Navigation and MVVM applications

(8 votes)
Levente Mihály
>
Levente Mihály
Joined Apr 27, 2010
Articles:   7
Comments:   16
More Articles
10 comments   /   posted on Jul 28, 2010
Categories:   Patterns and Practices , Design

This article is compatible with the latest version of Silverlight.

Expression Blend 4 comes with some pretty cool pre-built

VisualState transition-animations called TransitionEffects. A TransitionEffect is a pixel-based transition from one state to another, in other words it’s a PixelShader that has an animatable Progress property. These effects can be used in various scenarios, they are very developer/designer friendly, and they are an easy way to make your Silverlight application more attractive.

In this article I will show you two situations to use Blend 4’s built-in TransitionEffects:

- Navigating between pages in Navigation Framework and

- switching between Views in an MVVM (Light Toolkit) scenario.

Here are the two samples with the „Pixelate” and the „Slide In” effects, live demo and source codes:

Source code to MVVM Transition Demo

Live demo for Navigation Transition

Source code to Navigation Transition

VisualState and Transition recap

You probably know VisualStates from Silverlight SDK Controls and from custom Controls. The name of the concept is “Parts and State Model”. This means that every control has Parts (named elements within the Control) and States (and State Groups). Between switching from a state to another we can define transitions. VisualStateManager is the one that handles state-changes.

The States panel first appeared in Blend 2 SP1, in Blend 3 there were the pre-setted Easings for the transition storyboards, and now in the fourth version of Blend there are the TransitionEffects.

Here’s the standard Button’s States-view in Blend 4:

It’s good to know that we can use VisualStates and Transitions not just in custom Controls but in UserControls as well.

TransitionEffect in a Navigation Framework Application

To enable one of Blend 4’s new TransitionEffects in a Navigation Framework application, all we need is Blend 4 and zero coding. :)

  1. If you don’t have an existing navigation application in which you can test, create one using Visual Studio. Create a new project using the Silverlight Navigation Application template.
  2. Once you’re application is ready, open it in Blend 4. Open the main page (default is MainPage.xaml).
  3. Expand the LayoutRoot and put the ContentBorder in a Grid. You can do this by right clicking on the ContentBorder and selecting Group Into ->Grid. ContentBorder contains the ContentFrame. We will add the transition effect to the newly created grid.
     
  4. Luckily ContentFrame exposes both the Navigating and Navigated events. The first one fires before the navigation, the second one after the navigation is made. We will create two states according to these events, a “NavigatingState” and a “NavigatedState”.
    Select the States panel, and add a VisulStateGroup by clicking on the plus icon. Add two VisualStates to the group.
     
  5. Notice the “fx” icon next to the Default Transition. Click on it and from the dropdown select the TransitionEffect you would like to use. Some effects have additional options (for “Slide In” there’s the option for slide direction).
  6. Next to fx icon you can set an easing and the duration of the transition, mine is 1 second long.
  7. So now there will be an animation between the two states we created. Next step is to wire up the states. On the Assets panel in the Behaviors, there’s a behavior called GoToStateBehavior. In this Behavior we can connect an event with a state. Just what we need. Expand the “ContentFrame” Border element in the Object and Timeline panel. Drag a GoToStateBehavior to the ContentFrame. Then drag another one.
  8. Using the Behaviors, we can connect the NavigatingState with the Navigating event and the NavigatedState with the Navigated event. We can do this on the Properties panel of each Behavior.
  9. After the events are connected with the states, we can run the application and voila, the navigation is animated.
    Though you may notice that not only the content is animated, but the selected TransitionEffect is applied to the navigation links’ header also. This might be an unwanted side-effect. For a workaround, switch to XAML view, and move the whole VisualStateManager definition just inside the Grid we created in the first step. Something like this:
     <Grid x:Name="LayoutRoot" Style="{StaticResource LayoutRootGridStyle}">
                 
      
             <Grid Margin="0,0,0,0">
                 
                 <!-- VisualStateManager moved from LayoutRoot, just the Content will have the TransitionEffect -->
                 <VisualStateManager.CustomVisualStateManager>
                     <ei:ExtendedVisualStateManager/>
                 </VisualStateManager.CustomVisualStateManager>
                 <VisualStateManager.VisualStateGroups>
                     <VisualStateGroup x:Name="VisualStateGroup">
                         <VisualStateGroup.Transitions>
                             <VisualTransition GeneratedDuration="0:0:1">
                                 <ei:ExtendedVisualStateManager.TransitionEffect>
                                     <ee:SlideInTransitionEffect/>
                                 </ei:ExtendedVisualStateManager.TransitionEffect>
                                 <VisualTransition.GeneratedEasingFunction>
                                     <CircleEase EasingMode="EaseIn"/>
                                 </VisualTransition.GeneratedEasingFunction>
                             </VisualTransition>
                         </VisualStateGroup.Transitions>
                         <VisualState x:Name="NavigatingState"/>
                         <VisualState x:Name="NavigatedState"/>
                     </VisualStateGroup>
                 </VisualStateManager.VisualStateGroups>    
                 
                 <Border x:Name="ContentBorder" Style="{StaticResource ContentBorderStyle}" Margin="0">
     ...
Now when we run the application again, the TransitionEffect is only applied to content, the header will stay intact.

For the demo I added the “Slide In” effect to the Cosmopolitan Theme Sample. Notice when there are a lot of different controls on a page the transition might not be very smooth. That’s the case in the demo on the SDK Controls and Toolkit Controls page, where the page contains a lot of different controls. Loading all the controls takes long, it’s not the effect itself that is slow. Well, nothing is perfect.

TransitionEffect in an MVVM application

The second sample for using transitions is an MVVM application. Scenario is simple; we have a few Views and a menu. The user can select between the Views, and one is visible at a time. I really like Laurent Bugnion’s MVVM Light Toolkit for its simplicity and efficiency, so I’ll be using that.

We will create a DataTemplate selector ContentControl, and will bind the Content to the selected ViewModel. Let’s create the Views and ViewModels first.

  1. First, we can start a new application using the MVVM Light (SL4) template. The MainPage.xaml, the MainPageViewModel and the ViewModelLocator will be automatically created.
  2. We can add the a few Views and their ViewModels using the MVVM Light Toolkit templates (add new item: MvvmView(SL) and MvvmViewModel (SL)). Let’s call these OneView, TwoView, ThreeView and OneViewModel, TwoViewModel, ThreeViewModel.
  3. In the ViewModelLocator we must set up properties for the ViewModels. We can do this by using the “mvvmlocatorproperty” snippet. Once this is done for all three ViewModels, we can set up the DataContext bindings in the Views.
     DataContext="{Binding OneVM, Source={StaticResource Locator}}"
     private static OneViewModel _oneViewModel;
      
             /// <summary>
             /// Gets the OneVM property.
             /// </summary>
             public static OneViewModel OneVMStatic
             {
                 get
                 {
                     if (_oneViewModel == null)
                     {
                         CreateOneVM();
                     }
       
                     return _oneViewModel;
                 }
             }
      
             /// <summary>
             /// Gets the OneVM property.
             /// </summary>
             [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
                 "CA1822:MarkMembersAsStatic",
                 Justification = "This non-static member is needed for data binding purposes.")]
             public OneViewModel OneVM
             {
                 get
                 {
                     return OneVMStatic;
                 }
             }
       
             /// <summary>
             /// Provides a deterministic way to delete the OneVM property.
             /// </summary>
             public static void ClearOneVM()
             {
                 if (_oneViewModel != null)
                 {
                     _oneViewModel.Cleanup();
                     _oneViewModel = null;
                 }
             }
      
             /// <summary>
             /// Provides a deterministic way to create the OneVM property.
             /// </summary>
             public static void CreateOneVM()
             {
                 if (_oneViewModel == null)
                 {
                      _oneViewModel = new OneViewModel();
                 }
             }

The DataTemplate selector

For the DataTemplate selector we must create a custom ContentControl.

  1. Add a new class (in my case it’s called MvvmDataTemplateSelector) that inherits from ContentControl.
     public class MvvmDataTemplateSelector : ContentControl
         { 
             ...
         }
  2. Add a property - type of DataTemplate - for each property.
     /// <summary>
             /// DataTemplate for type OneViewModel
             /// </summary>
             public DataTemplate OneView { get; set; }
     
             /// <summary>
             /// DataTemplate for type TwoViewModel
             /// </summary>
             public DataTemplate TwoView { get; set; }
       
             /// <summary>
             /// DataTemplate for type ThreeViewModel
             /// </summary>
             public DataTemplate ThreeView { get; set; }
  3. Override the OnContentChanged method. In this method connect the ViewModel with its View, as we will bind the Content to the selected ViewModel.
     protected override void OnContentChanged(object oldContent, object newContent)
             {                        
                 // select ContentTemplate for ViewModel
                 if (newContent is OneViewModel)
                 {
                     ContentTemplate = OneView;
                 }
                 else if (newContent is TwoViewModel)
                 {
                     ContentTemplate = TwoView;
                 }
                 else if (newContent is ThreeViewModel)
                 {
                     ContentTemplate = ThreeView;
                 }
       
                 base.OnContentChanged(oldContent, newContent);            
             }
  4. Set up the MainPage and MainPageViewModel. We can add buttons for each view in the xaml, and in the MainPageViewModel we can add Commands. Each Command will set the SelectedViewModel property to a ViewModel.
  5. Finally we can host our Views in the newly created MvvmDataTemplateSelector. Now when we compile and run the application we can switch between the Views.
     <!--DataTemplates -->
                 <DataTemplate x:Key="oneView">
                     <Views:OneView />
                 </DataTemplate>
                 <DataTemplate x:Key="twoView">
                     <Views:TwoView />
                 </DataTemplate>
                 <DataTemplate x:Key="threeView">
                     <Views:ThreeView />
                 </DataTemplate>
      ...
     <Helpers:MvvmDataTemplateSelector
                                 Content="{Binding ActiveViewModel}"
                                 OneView="{StaticResource oneView}"
                                 TwoView="{StaticResource twoView}"
                                 ThreeView="{StaticResource threeView}"  
                                 HorizontalAlignment="Stretch"                      
                                 VerticalAlignment="Stretch"
                                 HorizontalContentAlignment="Stretch"
                                 VerticalContentAlignment="Stretch"
                             />

TransitioningContentControl

The easiest way to add transitions to our application is to use the Silverlight Toolkit’s TransitioningContentControl:

 <toolkit:TransitioningContentControl 
             Grid.Column="1" 
             Content="{Binding ActiveViewModel}" 
             Style="{StaticResource TransitioningContentControlStyle2}" 
             HorizontalContentAlignment="Stretch" 
             VerticalContentAlignment="Stretch">
                 <toolkit:TransitioningContentControl.ContentTemplate>
                     <DataTemplate>
                         <Helpers:MvvmDataTemplateSelector
                              Content="{Binding }"
                              OneView="{StaticResource oneView}"
                              TwoView="{StaticResource twoView}"
                              ThreeView="{StaticResource threeView}"  
                              HorizontalAlignment="Stretch"                      
                              VerticalAlignment="Stretch"
                              HorizontalContentAlignment="Stretch"
                              VerticalContentAlignment="Stretch"
                          />
                      </DataTemplate>
                  </toolkit:TransitioningContentControl.ContentTemplate>
              </toolkit:TransitioningContentControl>  

There’s one drawback, there are only three transition animations built in the Control. Luckily we can help that by editing its template, thus enabling Blend 4’s TransitionEffect.

  1. Open up Blend, and on the MainPage edit the TransitioningContentControl’s template (right click, edit template, edit a copy.) It will look like this:

    The Control consists of two grids, one for the previous content, and one for the current content, this way enabling a transition between them. Each Transition animation has a State, when you set the TransitionName property, you set one of the upper States. The transition will happen between the Normal state (we cannot delete this) and the selected one.
    To add a new animation, you can add a new State, and set-up a Storyboard for it. This time though we will enable one of the built-in TransitionEffects, by setting the Default transition just like in the Navigation Framework example.

  2. We can add a new State, or just edit the existing ones. I’ve edited the DefaultTransition: deleted the other States (this step is not necessary), deleted the DefaultTransition Storyboard, and in the State I set the PreviousContentPresetationSite to Collapsed, just like in the Normal state, because we will take care of this in the Default transition.
  3. Select the Default transition (the one with the TransitionEffect), and create a Storyboard, where you hide the PreviousContentPresentationSite halfway through the transition.

    At 0:00,000 the PreviousContentPresentationSite is Visible, at 0:00,500 it is Collapsed. The full transition is 1 second long. Of course you can change the timeline, e.g. when you are using a non-linear easing for the TransitionEffect.
    Here’s the code for the finished VisualStateManager:

     <VisualStateManager.CustomVisualStateManager>
         <ei:ExtendedVisualStateManager/>
     </VisualStateManager.CustomVisualStateManager>
     <VisualStateManager.VisualStateGroups>
         <VisualStateGroup x:Name="PresentationStates">
             <VisualStateGroup.Transitions>
                 <VisualTransition GeneratedDuration="0:0:1">
                     <ei:ExtendedVisualStateManager.TransitionEffect>
                         <ee:PixelateTransitionEffect/>
                     </ei:ExtendedVisualStateManager.TransitionEffect>
                     <Storyboard>
                         <ObjectAnimationUsingKeyFrames 
                             Storyboard.TargetProperty="(UIElement.Visibility)" 
                             Storyboard.TargetName="PreviousContentPresentationSite">
                             <DiscreteObjectKeyFrame KeyTime="0:0:0.5">
                                 <DiscreteObjectKeyFrame.Value>
                                     <Visibility>Collapsed</Visibility>
                                 </DiscreteObjectKeyFrame.Value>
                             </DiscreteObjectKeyFrame>
                         </ObjectAnimationUsingKeyFrames>
                     </Storyboard>
                 </VisualTransition>
             </VisualStateGroup.Transitions>
             <VisualState x:Name="DefaultTransition">
                 <Storyboard>
                     <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" 
                                 Storyboard.TargetProperty="(UIElement.Visibility)" 
                                 Storyboard.TargetName="PreviousContentPresentationSite">
                         <DiscreteObjectKeyFrame KeyTime="00:00:00">
                             <DiscreteObjectKeyFrame.Value>
                                 <Visibility>Collapsed</Visibility>
                             </DiscreteObjectKeyFrame.Value>
                         </DiscreteObjectKeyFrame>
                     </ObjectAnimationUsingKeyFrames>
                 </Storyboard>
             </VisualState>
             <VisualState x:Name="Normal">
                 <Storyboard>
                     <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" 
                             Storyboard.TargetProperty="(UIElement.Visibility)" 
                             Storyboard.TargetName="PreviousContentPresentationSite">
                         <DiscreteObjectKeyFrame KeyTime="00:00:00">
                             <DiscreteObjectKeyFrame.Value>
                                 <Visibility>Collapsed</Visibility>
                             </DiscreteObjectKeyFrame.Value>
                         </DiscreteObjectKeyFrame>
                     </ObjectAnimationUsingKeyFrames>
                 </Storyboard>
             </VisualState>
         </VisualStateGroup>
     </VisualStateManager.VisualStateGroups>

Summary

I hope I could show you in this short tutorial how easy it is to add a transition-animation to your application. The possible scenarios are endless, I’m sure everybody can find his own best way. You can even create custom TransitionEffects if you are familiar with the HLSL language.


Subscribe

Comments

  • ppopadiyn

    RE: Using Blend 4's new built-in TransitionEffects in Navigation and MVVM applications


    posted by ppopadiyn on Jul 28, 2010 15:01
    Nice one, especially the integration with the Navigation Framework will be very useful for me ;)
  • wildfox

    RE: Using Blend 4's new built-in TransitionEffects in Navigation and MVVM applications


    posted by wildfox on Jul 28, 2010 15:10
    thanks :)
  • -_-

    RE: Using Blend 4's new built-in TransitionEffects in Navigation and MVVM applications


    posted by Ian on Jul 29, 2010 11:36

    Many thanks for this, just the thing I've been looking for to build a 'Metro' style interface

  • -_-

    RE: Using Blend 4's new built-in TransitionEffects in Navigation and MVVM applications


    posted by billabong on Jul 29, 2010 16:27
    thanks, lots of useful information
  • -_-

    RE: Using Blend 4's new built-in TransitionEffects in Navigation and MVVM applications


    posted by Fallon on Jul 31, 2010 01:41

    The transition in the Navigation App wasn't very smooth for me, I was wondering if anybody else had noticed that.

    Also, what may be the cause, since my development machine is pretty powerful graphics and processor wise.

  • wildfox

    RE: Using Blend 4's new built-in TransitionEffects in Navigation and MVVM applications


    posted by wildfox on Jul 31, 2010 10:37
    Is it slow in your application or just in the demo? As I wrote in the article, the demo application loads all the sdk and toolkit controls, and that takes some time. You will notice that once it's in the memory it will get faster. Between "home" and "core controls" it should be smooth.
  • -_-

    RE: Using Blend 4's new built-in TransitionEffects in Navigation and MVVM applications


    posted by Fallon on Aug 01, 2010 10:43

    It's fast between the first two pages, but gets jerky on the last two, even after it's all in memory(yes, I'm using your demo).

    I had hoped that this would work, but since SL 2, it's always better to slide images or simple controls.  If you put a DataGrid on the page, it will get even worse.

    The best solution is to get a bitmap of the page and animate that, or stick with simple controls and text.

  • -_-

    RE: Using Blend 4's new built-in TransitionEffects in Navigation and MVVM applications


    posted by Aaron on Aug 03, 2010 17:03

    Hi there,

    I get the exception "Target LayoutRoot does not define any VisualStateGroups" when trying to run Navigation Transition project from source download.  Any thoughts?

  • wildfox

    RE: Using Blend 4's new built-in TransitionEffects in Navigation and MVVM applications


    posted by wildfox on Aug 03, 2010 20:08

    Fallon, I tried with only the datagrid on the SDK page, it became much better. There's only a little stop on the beginning, after that it is smooth.

    Aaron, I downloaded it, it works here. You can check that the visualstates are defined in the ContentBorder inside the Grid. The GoToStateActions are in the navigation frame. Maybe you can try removing them and calling the VisualStateManager manually.

  • darshandoshi

    Re: Using Blend 4's new built-in TransitionEffects in Navigation and MVVM applications


    posted by darshandoshi on Nov 28, 2011 20:32

    hey i am still not understanding this

    can u please upload the video of your own

    step by step

    so that i can learn 

    thanks

Add Comment

Login to comment:
  *      *