Property triggers are the WPF feature I miss the most in Silverlight 2: I really liked writing behaviors in declarative style with XAML and Styles and it was somehow frustrating being forced to use C# code and event handling to achieve similar results in Silverlight.
Although it's not here for exactly the same puropose, VisualStateManager is a great improvement to fill the gap thanks to:
- Blend visual support
- automatic state transition animation
Those two features, combined with the opportunity to inject custom states at your own will, make VisualStateManager so poweful that you're going to miss it once back to WPF, at least until it won't be supported for smart clients too.
Let's suppose I want to animate a textbox to change its background color when mouse pointer overs it. If I was in WPF I would have attached a trigger to the IsMouseOver property, in Silverlight we got no triggers, but we have Blend and VisualStateManager.
So what I do is putting a TextBox in my UserControl and ask Blend to customize its template:
As we can see, we got no states for the standard TextBox so VisualStateManager seems to be unuseful at first: should we once againf rely on procedural code to achieve our goal? Not at all (or, more exactly, almost not at all). Even though standard TextBox has no built-in states (it doesn't specify any in its attributes nor it invokes any state transition, as, for example, Button does) we can easily add our own simply editing the generated style XAML markup.
What we need is a custom StateGroup, called MouseStates, and a couple of states, Normal and MouseOver, so what we do is opening Visual Studio to have intellisense while typing, adding a reference to System.Windows namespace and writing the following lines of code:
Visual Studio complains about using VisualStateManager.VisualStateGroups attached property; however, don't care about it, everything will compile without errors. Ok, now back in blend to continue editing the control template:
As you can notice, Blend recognizes the 2 newly added states and suddenly adds them to the States panel. Now, we can animate the TextBox background as we would usually do:
Now we only need one last step: adding some code to invoke state transitions when the mouse pointer overs or moves away from the TextBox. So, back in Visual Studio, let's add a couple of event handlers:
Now, if you build and run the project, you'll notice how the TextBox gracefully changes its background color from white to shaded red. However, our textbox won't work in another UserControl unless we don't add the same event handling code to it. It would be preferrable to build a custom StateTextBox and internally hiding all that logic. Doing it is extremely easy, as it consists only on creating a class which inherits form Textbox and writing code similar to the previous one:
Notice the two attributes I added to the class declaration to describe the control's state machine structure; Blend is supposed to read them to show controls states when editing its template. Unfortunately, (as I wrote some days ago) Blend June CTP current version has template editing capabilities only for controls which belong to System.Windows.dll. It means that even if we use StateTextBox, we'll still need to manually do all the stuff. However, it still has the advantage to leave the page code behind free from any textbox state transition code.
As usual, source code is available here.
