The team blog of the Expression Blend and Design
Click here to watch Kenny’s MIX 2010 session that covers a lot of the topics that you see in this post.
In Expression Blend, we’ve been thinking for a loooong time about how to make it ever easier to create great animated visual effects quickly on top of the Silverlight and WPF runtimes. We’ve been looking at large-scale animation needs since Blend 2 SP1 and steadily building features to address those needs, and we think we’ve reached critical mass. With Blend 4, we have a compelling set of technologies that work very well together.
This blog post is a companion to the “Dynamic Layout and Transitions” demo app that we’ve placed in the Expression Gallery at http://gallery.expression.microsoft.com/en-us/DynamicLayoutTrans. That app shows off the features whose motivations are described here.
Since its inception, Blend has offered keyframed editing of Silverlight and WPF properties via Storyboards. While I won’t go into specific details on that here, it forms the basis for all the features described below. Some of these features work directly from Storyboards you create and others create Storyboards behind the scenes on your behalf – and sometimes both.
Let’s start by turning the clock back two years. In Expression Blend 2 SP1, we introduced the States Panel, which edits VisualStates and VisualStateGroups for Silverlight 2 (and WPF 3.5 with the WPF Toolkit). This introduced the notion of a “state” as a means of communication between visuals and code, and made it dramatically easier to describe a set of visual changes. Based on input, the control code could decide when to enter what state, and the visuals would decide what changes were present in that state plus how long it took to transition between any pair of states (e.g. you might want most state changes to take 0.25s, but want Pressed state changes to be instantaneous).
This proved to be a very effective tool, but it had limitations. The core VisualStateManager runtime (which we’ll call “VSM” from now on) could only do linear interpolations of the values being set. This works great for opacity and transform offsets, but doesn’t work well for discrete properties or data that isn’t known until runtime. Also, not all animation scenarios are driven by state changes. So we put our thinking caps on about how we could get more scenarios to work in a way that designers could rapidly tool the effects.
In V3, we added four primary enhancements in this area. The first was EasingFunctions, which are critical to making property animations have the right feel. We’ve got all the classics – quadratics, cubics, bounce, elastic, etc. Plus, you can write your own EasingFunction in C# or VB and apply it to any animation you wish. This is all supported in Silverlight 3 and WPF 4. EasingFunctions can be applied to an individual animation or keyframe, and you can apply a default EasingFunction to your entire state transition.
The second was a GoToStateBehavior on top of Blend’s Behaviors engine, which made it easy to program all your state change logic directly in the markup without code. Like all of Blend’s Behaviors, you can simply drag it from our Asset Panel onto any elements you choose.
Those two enhancements just made the existing scenarios run better. We also wanted to address new classes of scenario. The first one we tackled was the issue of elements moving in a StackPanel or WrapPanel. Traditionally, these elements have snapped into place as an application changes elements or changes size, and we wanted a smooth transition that users could control. So we introduced the FluidMoveBehavior to make it easy for an element to watch the layout manager for when it moved to a new spot, and smooth out its progress with an animation controlled by one of those EasingFunctions we described earlier. So now it’s easy to have your elements animate into place at a speed you choose!
Here’s a picture of the feature in action. There’s no more room on the first line for the purple rectangle, so it’s moving to the beginning of the second row and the other elements are moving to make space. Technically, from a layout perspective, the elements in motion are actually at their destinations already – but by adding the appropriate transforms on top, we make the change look smooth from the visual perspective that users care about.
The fourth enhancement we made was the most challenging for us. We noticed that many times, customers wanted different states in their control to have different layouts entirely, but still respond to active layout changes in the application. For example, one layout might have a set of task panes visible outside the working area, and another might have one or more of these panes hidden. Customers wanted to describe these different layouts with states to get a good separation between their visuals and their business logic, but the properties that needed to change between these states weren’t properties that could be smoothly interpolated. For example, how do you interpolate between Visibility.Visible and Visibility.Collapsed?
What we learned was that in cases like these, users weren’t satisfied with the direct property animations that our system provided – they just wanted it to “look right”, and making it “look right” required that we animate a morph of the change rather than the change itself. So we wrote an engine that would take a layout snapshot before the state change, take another layout snapshot after the state change, and create a smooth morph between the start and end positions, employing the duration and EasingFunction of the user’s choosing. We dubbed this “FluidLayout”, and you can turn it on here:
Just click that little button, and all your layout changes in that VisualStateGroup will be animated between states even when it seems impossible. We’ll even simulate a Visibility change by means of an opacity simulation. Note that you’ll have more success if you click this before you start making layout changes – otherwise, when you move an object, it’ll create translate/scale animations that don’t respect layout, because that’s the best that the standard VSM can do.
It’s hard to do justice to this feature in a picture, but here’s my best attempt. In this example, the Timeline Pane is in the process of shrinking to the leftmost column, which I configured by changing the Pane’s Grid.ColumnSpan property in a state. Similarly, I changed the RowSpan of the pink rectangle, and it is in the process of growing taller as a result.
In Blend 4, we’ve managed to take these themes even farther, and have three more toys for designers to play with. Let’s start with animating things in and out of lists. In V3, you could apply a FluidMoveBehavior to your ListBox, and the other items would dutifully make room for your new item or close up the space. But there wasn’t any easy way to effectively control the item that was itself being added or removed; if you were clever, you could rig up some events to make an element animate on entry, and you had to be really really clever (and pollute your data model in unfortunate ways) to make an element animate on exit. We worked closely with the Silverlight team to produce a solution here that you can tool effectively, and it’s called LayoutStates. To find them, first edit the ItemContainerStyle:
And then, note these three new VisualStates in the States Panel:
You can use these states to model what an element looks like just before it’s loaded, what it looks like after it’s been loaded, and what it looks like just before it’s unloaded. Silverlight will then animate the state changes for you at the appropriate times, as your items are added to or removed from the list. Remember to add a FluidMoveBehavior to the ItemsPanel template (note its presence in the Edit Additional Templates submenu, a couple of pictures above), and set AppliesTo = Children, to get the other elements to move out of the way. Note that if your ItemsPanel is a VirtualizingStackPanel, your ListBox should have VirtualizingStackPanel.VirtualizationMode set to Standard, or you should learn one of the other new tricks below.
Here’s an example of this in action – the middle item is just entering the list.
The next feature we added is another in the vein of simulation. In V3, we added FluidLayout to VSM in order to get a smooth and realistic morph between two states, but it got us to thinking about the other sorts of morphs we could perform. Enter TransitionEffects. Whereas transition effects in video editing provide a pixel-based transition from one video clip to another, Blend’s TransitionEffects provide a pixel-based transition from one state to another. In Blend, a TransitionEffect is a PixelShader that has an animatable Progress property. We are shipping several of these in our SDK, and if you know HLSL you can write your own. Here’s how you set one up:
As configured here, all state changes in the LayoutStates group will perform a “Smooth Swirl Grid” pixel-based TransitionEffect, taking one second and with a cubic ease. You can of course set a different transition for any individual state change if desired. Some of the TransitionEffects have properties to further customize them; for example, Smooth Swirl Grid lets you control the level of subdivision and the intensity of the twisting effect, but those properties are under the combo dropdown in the picture. Here’s a screenshot of that TransitionEffect in action:
The final feature we added is something that we’ve been trying to wrap our minds around for five years. We’ve noticed that in a lot of applications, visuals will move from one part of the application to another even though the visuals are often generated from data. In a true MVVM design where the data model should know nothing about the visuals, it’s extremely challenging to get these kinds of effects.
What we’ve done is train the visuals to learn more about the data model – specifically, to train FluidMoveBehavior to associate positions with data instead of with visuals. This needs a little bit of explanation, but is remarkably easy to use – you can create an animated list-detail example from scratch in about two minutes.
Here’s a picture of such an app:
What we want is for the large chair in the details view to appear to grow out of the small chair in the master list. All we have to do is locate the Image element in the ItemTemplate for the ListBox, and give it a FluidMoveTagSetBehavior that will register it with the FluidMove system. That looks like this:
Note that the Tag property indicates that element will be tagged according to its DataContext, which is the model item behind the visuals. Next, there’s a FluidMoveBehavior on the detail Image, which looks like this:
The other half of the connection is made with the InitialTag field that is set to DataContext. This means that when the detail element appears, it will consider the registered position of its DataContext to be the place it will appear to come from. And that’s the whole thing! Here’s a screenshot of that app in action; note that in this case I set the FluidMoveBehavior on the entire Grid, so that the details would animate along with the image.
There’s an awful lot happening behind the scenes, but we’ve managed to boil this complex scenario to these two simple properties. This system can even be used to animate objects from one list to another list.
If I had included all of our future investigations in this area, this blog post would be twice as long as it is already. We’re working hard to address more and more scenarios in the simplest ways possible. Rest assured that you’ll be hearing about even more improvements someday in the not too distant future!
If you have any opinions or feedback, please feel free to comment below.
Kenny Young Architect, Expression Blend
Fantastic post. In fac -t I am presently working on an SL4 MvvM app that needs a visual very similar to the last example with the expanding chair. I think you just saved me a ton of time. Kudos to you and the team for another excellent SL release.
Er, why not include a link to a functional page instead of forcing everyone to download and build the sample?
Jay - the sample is based on Silverlight 4 RC and Blend 4 Beta. The current licensing on both specifies that we can't generally display samples outside of source code form.
Once we RTM Silverlight and Blend 4, we'll try to get a working example of all this so that you can view them in your browser.
This is sooo good! I have dreamed of having such things since day 1 (and actually I have built a few of those abstractions myself, e.g. the automatic layout animations, or animated items insertion).
One thing gets me worried, though. Is the "Present 2010" available in WPF 4? I'm especially concerned with LayoutStates, which I haven't seen outside SL discussions. As you wrote, animating items insertion and removal is a huge visual improvement, but it's very hard and annoying to implement with today's API. I would be extremely disappointed if this is a SL-only feature at the release of WPF 4.
Congrats on those, we're going to see awesome WPF/SL UI in the future!
We're extremely gratified to hear of your excitement and interest :-)
Unfortunately the LayoutStates feature is indeed unsupported on WPF 4. Happily, however, that's the only feature in the demo that is not available for WPF 4. We expect that this will be addressed in a future WPF release.
Just a nitpick. You probably meant the GoToStateAction instead of the GoToStateBehavior in the Recent History (2009) section. The difference being an Action instead of a Behavior.
I have to congratulate you on another excellent release! This stuff is just amazing and enables new levels of capability that would otherwise not be feasible.
However, I do have to nitpick and express my sadness that LayoutStates are not supported in WPF. In the past, Silverlight has always had the cool new features well before WPF. With this release I see that the two are becoming closer in terms of feature parity. This excites me as it is annoying to find that WPF has been lacking in the past while Silverlight enjoys rich new feature sets. The Visual States system is the first thing that comes to mind.
Is it Microsoft's intention to ensure that, as time goes on, WPF will get all of the features that Silverlight has? Do you have any plans for ensuring feature parity with each new release as opposed to releasing new features for Silverlight and then WPF later?
Thanks and keep up the excellent work!
That expanding Chair feature is fantastic !!
Thanks microsoft for making the MIX10 sessions available on the web.
Loved your Dynamic layout session - short - sweet and hitting all the right spots
Now I've no excuse in sticking with VB6
I've just run the example and the Fluid Move Behaviour has blown my mind.
Hey, i was at your mix presentation and my face was blown off. I love fluid movements so much! I do however have a small issue. Ive been building up a demo, and in the demo i am using WPF4. I have set up all listbox item as the FluidMovmentTarget, and I have a large area where I want the resulting information to expand from, much like your demo with the chair scaling out of the listbox. Everything works great as it stands, however I have additional functionality where the listbox containing all the images, is nested in a grid which has 2 rows, the listbox is in row 1 of the 2, with no row span. Using a standard button, I then animate the listbox to span both rows, and using the FLuidLayout option in the VSM, it animates very nicely. Now my problem is, as soon as I animate the spanning of the rows, the FluidMovmentTarget seems to break, and then all the images for the rest of the application session originate from 0,0. What can i do, to not make that happen? =D
Good catch - this will be fixed before we release. It's now working on my machine... :-)
Thanks to you too!
I'm seeing an issue where I cannot set any transforms in blend in a ListBoxItemTemplate. I can see the value change as I move my mouse but then Blend is resetting the value to 0. If I look in the xaml nothing is changed in the states? Any ideas?
JS, I'm not sure what you mean here - as best as I can interpret your issue, this is working for me. If you want to discuss your scenario further, you can send me mail at kennyy@<that company that I work for>.com, and I'd be happy to help.
I'm not sure if you know about the ScatterView control from the Surface SDK. I'm wondering how can I animate the items into certain arrangement with a click of a button. Is it something I could do now with the current release of WPF/Silverlight?
Sorry, I don't have enough experience with ScatterView specifically to be sure. It looks like ScatterView does more of its work via RenderTransforms than with layout properties, which would not match up with this approach...yet :-)