You may have noticed the new look for the Twilight Twitter Badge on my blog a few weeks ago. I wanted to add a few new looks for the badge and got one of them done but then decided I need to spend some more time on it before releasing it because I didn’t like the way the code was turning out. There were a couple of things I didn’t like:
- The code was too tightly coupled to the views/skins. This made it hard to add new views/skins without duplicating code.
- The views/skins weren’t blendable at all.
To start my rework I began with this post by the Expression Blend/Design team on simulating sample data in Blend. The post is a very simple yet workable solution for displaying design time data in Blend so that you can work on the layout of your application. The only change I made was how I detected design mode. After playing around with that sample I decided that to implement this in Twilight I would need to switch to a Model-View-ViewModel approach so I started doing some research into using this approach with Silverlight. In my research I came across this post by Ryan Keeter on using MVVM in Silverlight. It was a nice simple explanation that made sense to me so I set out to combine the expression team example and this MVVM example.
What I ended up with is pretty close to MVVM. I say pretty close because I don’t think it fully fits since the ViewModels hook into some of the Views Storyboard events and also control the Views VisualState transitions. Maybe that fits into MVVM, but it probably breaks some of the rules. However, for this tiny application it makes things a lot easier. I still have multiple Views per ViewModel and the Views have zero code which is what I really wanted.
There are two ViewModels that I’m using: ListViewModel and RotatingViewModel. Then on top of these two ViewModels are four Views: Default, Large, Small, and Tiny.
ListViewModel Views |
|
|
|
Default View
|
Large View
|
The ListViewModel is for views where there is just a list of tweets while the RotatingViewModel is for views that display a single tweet at a time.
RotatingViewModel Views |
|
|
|
Small
|
Tiny
|
You can switch between these views by setting the mode initParam equal to the view you want (example: mode=tiny). The Tiny view looks like the twitter counter badge but then pops the bubbles over the surrounding content. This is done using the windowless = true parameter and absolute positioning. Right now the Silverlight will float over the content below it even when the bubble isn’t showing, so you won’t be able to click through to that content. I might be able to figure out a better way to handle it, but for now that is a known limitation.
Since now all the view logic is in the ViewModel, writing tests is a lot easier. I’m still using the same Silverlight test framework, but thanks to this post by Justin Angel I added a few more complex tests using his WaitFor extension. The test coverage is still very light and I’m not testing the views at all, but I feel like I’m starting to get testing in Silverlight.
I’ve also added another option for hosting Twilight on your blog. You can now host it via Silverlight Streaming using an iframe. Add the following HTML to your page:
** Hosting it via Silverlight Streaming doesn’t support the Tiny mode since the Silverlight won’t be able to expand outside of the iframe.
In addition to hosting it via Silverlight Streaming, you can always self-host it or use the xap I have hosted on dreamhost at http://twilight.bryantlikes.com/twilight.xap. If you’re already using the hosted version, you can switch the mode by using the mode initParam as I mentioned above.
Hopefully this will serve as a great twitter badge for your blog and also a decent example of MVVM in Silverlight along with some unit testing examples as well. Feel free to join the project on Codeplex and create your own views. I am still working on at least one more version that will make the colors tweakable and maybe even detect what colors should be used based on the surrounding html.