Finding a Storyboard in the VisualStateManager

A few weeks ago in the Silverlight forums, a user asked how they could attach to the OnCompleted event of a Visual StateManager animation.  At first, this sounds trivial, but the VisualStateManager does not directly expose a way to obtain a Storyboard.  However, the VisualStateManager does return a list of the VisualStateGroups through the GetVisualStateGroups method.  We can take advantage of this method to obtain a reference to the desired storyboard.

The FindStoryboard method defined in this helper class iterates over each of the VisualStateGroups until it finds a match, it then iterates over each Visual State in the group until it finds a match.  The Storyboard for the matching visual state is then returned.

public class VisualStateManagerUtils
{
public static Storyboard FindStoryboard(FrameworkElement parent, string groupName, string stateName)
{
var vsgs = VisualStateManager.GetVisualStateGroups(parent);
foreach(VisualStateGroup vsg in vsgs)
{
if (vsg.Name != groupName)
continue;
foreach (VisualState vs in vsg.States)
{
if (vs.Name == stateName)
return vs.Storyboard;
}
}
return null;
}
}

Now, it’s a simple matter of calling our helper method and doing something useful with the Storyboard reference.  For example, you could attach an event handler to the Completed event on the Storyboard.

    public partial class Page : UserControl
{
public Page()
{
...
Storyboard sbHidden = VisualStateManagerUtils.FindStoryboard(LayoutRoot, "CommonStates", "Hidden");
sbHidden.Completed += new EventHandler(sbHidden_Completed);
}

void sbHidden_Completed(object sender, EventArgs e)
{
// Do something cool here. } ... ...



Update
: Bart Czernicki had an excellent suggestion of making this method an extension method.  The resulting syntax is much more concise and easier to use.  With a few small changes, we can convert the helper method into an extension method.

public static class VisualStateManagerUtils
{
public static Storyboard FindStoryboard(this FrameworkElement parent, string groupName, string stateName)
{
var vsgs = VisualStateManager.GetVisualStateGroups(parent);
foreach (VisualStateGroup vsg in vsgs)
{
if (vsg.Name != groupName)
continue;
foreach (VisualState vs in vsg.States)
{
if (vs.Name == stateName)
return vs.Storyboard;
}
}
return null;
}
}

Now, it is much simpler to call the method

Storyboard sb = LayoutRoot.FindStoryboard("CommonStates", "Hidden");



Feedback

# Silverlight Cream for November 06, 2008 -- #421

Gravatar In this issue: Boyan Nikolov, Scott Hanselman, Page Brooks, Justin Angel, and John Papa. If you haven 11/6/2008 12:22 PM | Community Blogs

# re: Finding a Storyboard in the VisualStateManager

Gravatar I did someting similar...you might want to make it an extension method though. It is MUCH cleaner that way:

Change the definition to be:
public static Storyboard FindStoryboard(this FrameworkElement parent, string groupName, string stateName)

and then you can call it like this directly off of the LayouRoot object for example: LayoutRoot.FindStoryboard("CommonStates", "Hidden");
11/7/2008 1:34 AM | Bart Czernicki

# re: Finding a Storyboard in the VisualStateManager

Gravatar Great idea! I've updated the post with your suggestion! 11/7/2008 8:21 AM | pbrooks

# re: Finding a Storyboard in the VisualStateManager

Gravatar It seems you are overusing foreach and imperative approach.

Functional approach is much clearer.

return VisualStateManager.GetVisualStateGroups(parent).Select(vsg => vsg.States.SingleOrDefault(vs => vs.Name == stateName)).SingleOrDefault(); 11/8/2008 9:10 AM | Marcin Kosieradzki

# re: Finding a Storyboard in the VisualStateManager

Gravatar I made a mistakte writing my code - it should be of course: VisualStateManager.GetVisualStateGroups(parent).Where(vsg => vsg.Name == groupName).Select(vsg => vsg.States.SingleOrDefault(vs => vs.Name == stateName)).SingleOrDefault(); 11/8/2008 9:52 AM | Marcin Kosieradzki

# Silverlight Cream for November 11, 2008 -- #424

Gravatar In this issue: Ian Griffiths, Matthew Casperson, Chris Anderson, IDV Solutions, Nikhil Kothari, Dave 11/11/2008 12:25 PM | Community Blogs

# Initializing the FROM value of a Silverlight 2 Animation

Gravatar Recently, I was attempting to create my own popup dialog. I had specific requirements in mind for this 1/12/2009 3:54 PM | Rik Robinson's Blog

Comments have been closed on this topic.