Michael Wolf
{Binding ME}
Monday November 05, 2007
Silverlight, no routed events... no problem.
One of the things I miss in Silverlight which we have in WPF is routed events and routed commands. Language features, are a funny thing... when you first encounter them, you think do I need this? Then once you use them you can't imagine developing without them. This is the classic silverlight story. As a .net developer we come to love the framework and all it has, but the simple physics of fitting all the power of full blown 3.5 framework in the size of the agclr(4.5mb)... is like fitting a hummer into a space designed for a smart car. Just won’t fit. So we lose stuff, like routed commands and events. Which sadly means the ability for 1 element to bubble an event up or down the visual tree becomes allot more complicated. You’re left with just standard .net events.
While working on some silverlight projects, this became pretty frustrating to build out custom controls which can act independently but work seamlessly together.
Yet due to the power for that same trimmed down framework, nothing stops us from making our own event model to help us along. So I created a silverlight message bus, somewhat modeled on how we deal with events in our Flex projects. The Bus allows you to publish and subscribe to events, without having to be aware of the objects who fired or are subscribed to them. To highlight its use I created a simple game, well because everyone loves a game (especially a simple one written in silverlight 1.1 alpha using ms blend/ ms design / and orcas beta 2).
running example:
Launch in new window
try not to laugh at the animations or my little xaml duckies, look to Rick to wow you with silverlight ux stuff soon.
Basic idea, is that each duck can publish out an event that it was hit. The individual ducks are not aware of each other. So when you click on a duck we can fire an event to the other ducks and the main canvas, telling them there was a hit.
EventDispatcher.Publish(this, new CynergyEventArgs("Hit", this));
Then the page and each duck gets a message telling them there was a hit. In this case, the ducks then will do their little flip.
...
EventDispatcher.Subscribe(FlipOut);
...
[Action("Hit")]
private void FlipOut(object sender, CynergyEventArgs e)
{
OthersHit.Begin();
}
...
Now the page or the duck doesnt have to know that the hit was caused by a duck, or a dog or any object in particular. It just needs to listen for a hit event to be published through the bus.
The bus it's self is very lightweight and very simple, based on a simple pub / sub pattern, which keeps track of all the subscribed delegates and keys. The addition of linq into the 3.5 framework makes this a breeze. In the following snippet "events" is a generic List<> of events and "e" is the specific event to be fired.
... IEnumerableIt’s really helped me simplify the process of making lots of different objects all talk to one another. The cool thing about this method is, it’s not just silverlight specific. I didn’t just recreate routed events/commands , I’ll wait for msft to do that... this is just yet another way to skin the event cat. So becuase of that you can, and I do :), take the exact same code recompile it against the full clr and work with in a wpf application with no changes. Silverlight and WPF really do allow true write once run anywhere... but thats a story for another blog post.results = from ev in events where ev.Action.Equals(e.Action) select ev.Handler; foreach (CynergyEventHandler d in results) { d.Invoke(sender, e); } ...