In this article, I want to illustrate an interesting aspect of Silverlight visual states and how they can be used in controls. You can read my blog here: Cellbi Blog.
It is not a secret that one of the key features in Silverlight controls is an ability to declare different states for a control and specify transitions between them.
Each transition between states can take time for animation, and often, it is necessary to know when a transition is really finished. Let us suppose that we've spent a couple of hours and prepared a simple button in Blend. Something that looks like the following picture ;-)
The button above consists of three parts:
LayoutRoot (a grid with width and height bound to the "
Width" and "
Height properties of the control),
Host (a button background with color property bound to the "
Background" property of the control), and
Content (a green arrow).
Visual States in XAML
Here is the result of such efforts in xaml code, which specifies simple style for the button.
<vsm:VisualTransition GeneratedDuration="00:00:00.4000000" To="MouseOver"/>
<vsm:VisualTransition GeneratedDuration="00:00:00.4000000" To="Play"/>
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
Now, we need to add behaviour logic to this button. It should have two methods:
Stop. When the mouse moves over the button, the host should change its opacity. When the
Stop method is called or the button is simply clicked, the content should start rotation - the play state of the button.
Working with Visual States from C# Code
Ffrom the point of implementation, this can be done in the following way. As you can see from the picture, the button has three states: "
MouseOver" and "
Play". When the mouse pointer is moved over the control, we should start transition to the
MouseOver state, and when the button is clicked, we should start transition to the
Play state, and only after that, we start the rotation of the content.
Please note: "only after that" start the rotation of the content ;) The problem is that transitions between states can take time. And, if you start rotation of the content immediately after the button is clicked - it will occur in parallel mode with the transition, and trust me, it will look really ugly. So, to avoid this, we definitely should start the rotation after the transition is finished.
Silverlight has an easy way to do exactly this. We can use the visual state manager and visual states. The XAML code contains a
VisualStateManager which declares VisualStates and Transitions. So, to implement our task, we simply need to get access to the
VisualStateGroups in the
OnApplyTemplate method override and handle several events. Let's take a look how the code would look like:
public override void OnApplyTemplate()
FrameworkElement root =
GetTemplateChild("LayoutRoot") as FrameworkElement;
commonStatesGroup = GetVisualStateGroup(root, "CommonStates");
VisualStateGroup GetVisualStateGroup(FrameworkElement root, string groupName)
if (root == null)
IList groups = VisualStateManager.GetVisualStateGroups(root);
if (groups == null)
foreach (VisualStateGroup gr in groups)
if (gr != null && gr.Name == groupName)
void HookVisualStateGroupEvents(VisualStateGroup group)
if (group == null)
group.CurrentStateChanged += group_CurrentStateChanged;
void group_CurrentStateChanged(object sender,
if (e.NewState != null &&
e.NewState.Name == "Play")
Now, let's see what is done in the above code. First, we get access to the "
CommonStates" visual group in the
OnApplyTemplate method, and then simply subscribe to the
VisualStateChangedEventArgs in the handler gives us only three properties:
NewState. However, this is all we need in this handler. ;-) When our event handler is called, we can say that the control was animated and we know which states the animation was done for. From this point, we know that the state of the control was changed and we can start content rotation.
I hope this sample will be useful.