Running Custom Code / Firing Custom Events from Within Storyboards

image

I’ve been doing a lot of animation sequencing (i.e. creating really big storyboards) in Silverlight lately and it’s not uncommon for that sequence to need to include some kind of non-storyboard-able event (like kicking of some media or calling some function).  I might, for example, want to start an audio file a 4.5 seconds into the animation.  I’ve approached this a couple of different ways now, but finally came across one that I’m happy with.

The trick to this is to know that Storyboards can actually contain other storyboards.  So something like this:

<Storyboard>
  <Storyboard ... />
  <Storyboard ... />
  <DoubleAnimation ... />
  <DoubleAnimation ... />
</Storyboard>

 

is completely valid.  It’s also just fine to put a duration on a Storyboard even if doesn’t do anything (e.g. contain any animations).  Remember?  That was the trick we all used to get frame based animation rolling before we had CompositionTarget.Rendering.

So the trick to getting your code to run in sequence with the animation is to insert an empty Storyboard, set its duration and handle the storyboard’s completed event.  It looks like this:

<Storyboard>
  <Storyboard Duration="00:00:04.5" Completed="PlayAudioFile1" />
  <Storyboard Duration="00:00:09.0" Completed="PlayAudioFile2" />
  <DoubleAnimation ... />
  <DoubleAnimation ... />
</Storyboard>

 

That would, of course, call the PlayAudioFile1 event handler at 4.5 seconds and PlayAudioFile2 at 9 seconds.  It works great and it’s super simple to manage.

I like this approach for a few reasons:

First, because it keeps the whole sequence within a single storyboard—super clean.  Other approaches I’ve tried have not been so nice.

Second, the storyboard stays reasonably “Blendable.”  Blend essentially just ignores the child Storyboards.  Ideally you would be able to set the duration on them from within Blend, but for now ignoring is nice.  It leaves the rest of the Storyboard Blend-editable.  Incidentally, I put the storyboards at the top because Blend tends to insert at the bottom.  If you put your child Storyboards at the bottom of the list, they have a tendency to get lost in the middle somewhere once Blend has its way with your XAML.

Finally, it gives a lot of flexibility in how you write your code.  You’re essentially just handling the completed event so you can write whatever fancy code you care to.

If you’re interested, some failed attempts have included:

  • “Chaining” storyboards, i.e. breaking up the storyboard into parts and then starting part2 (as well as calling my custom code) in the completed handler for part1, etc.  This was got messy quickly.
  • Creating a “parallel” DispatcherTimer that gets started along with the Storyboard.  This one was even messier.
  • Sequencing my events using tweening libraries or a custom sequencer helper that I created (instead of using Storyboards).  This one worked pretty well but had zero tooling support.

I may be missing a more obvious way to approach this.  Seems like a relatively common task, but I couldn’t find good information about how to do it.  If you’ve found a better (or different) approach, I’d love to hear about it.

6 comments

Bryan

08 dec 2008

 

I really like this approach. Great job!

 

Fabse

09 dec 2008

 

Hi,

I am not really into wpf/silverlight and all that stuff, but is there no standard fo launching sound within a storyboard? is custom code really needed? If not, would it be better anyway to directly implement a ?

 
 

[...] Robby Ingebretsen on Running Custom Code / Firing Custom Events from Within Storyboards [...]

 

Robby Ingebretsen

09 dec 2008

 

@Fabse: you would think there would be a better way to kick of a sound in a storyboard wouldn’t you? WPF has an element specifically for this (MediaTimeline) but I don’t believe Silverlight has the equivalent yet…although I’d love to be corrected. If someone knows of an all markup way to kick off some media in a silverlight storyboard, please share… For now, I think that this is just an area where Silverlight is still catching up but I would expect to get something like that soon…

 

Mike D

09 dec 2008

 

Great post. All of this reminds me of the early days of Flash Dev, when you had to come up with creative ways to overcome limitations of the tools/platform.

 

wolfshow

11 dec 2008

 

good idea!