09 November 2008

Silverlight: dynamically finding a storyboard in the VisualStateManager

Okay, I haven't been writing about Silverlight for quite a while, but here I am again!

Today, I'll discuss dynamically finding a storyboard in the VisualStateManager.

Basically, when you want to refer to some object, you set the x:name and there ya go. Here, things aren't half that simple.

In August/September, I used the following code, inspired by something posted on the official forums:

var query = from trans in
(from stateGroup in
VisualStateManager.GetVisualStateGroups(LayoutRoot)
where stateGroup.Name == "VisibleStates"
select stateGroup).First().Transitions
where (trans.To == "Visible" && trans.From == "Hidden")
select trans;

Storyboard sb = (Storyboard)query.First().Storyboard;
Ugly like an ugly workaround, but it worked in Silverlight 2 beta 2. But then Silverlight 2 came out and that didn't compile anymore.

I needed to recompile my code fast, so without thinking too much, I wrote a double foreach. Ugly too, but it worked.

And then, one beautiful morning, the SilverlightNews Twitter pointed me to an article just about that. "Great", I said to myself, "I'll see a the right way of doing that." I clicked and saw... a double foreach! I felt smart for a while, but I had a hard time believing that this way was the best. So I asked Boyfriend.

Boyfriend has a bad influence on me because he gives me way better answers than Google - and shouldn't people google instead of bothering others? This time was no different - Boyfriend wrote a single-line solution and posted it in a comment over there.

I decided to follow his advice and rewrite my code the same way. After sweat, tears and another Boyfriend bother, I got this:
Storyboard sb = VisualStateManager.
GetVisualStateGroups(n.NodeLayoutRoot).
Cast<VisualStateGroup>().
Where(sg => sg.Name == "VisibleStates").SingleOrDefault().\
Transitions.Cast<VisualTransition>().
Single(t => t.To == "Visible" && t.From == "Hidden").
Storyboard;
No doubt it's single-line, no doubt it's shorter. Whether it's nicer, easier to write or more effective than a double foreach, we can discuss. I guess it's easy if you know Linq, which I don't. Wait, I do, I just wrote my first piece of it!

2 comments: