Saturday, 19 July 2008

Refactoring Silverstone - Removing static container and cleaning up the Shell

Hey readers, hope all is good! Firstly to apologise on having been fairly quiet on the Silverstone / Silverlight blog postings, especially with regards to my series on architecting Silverlight applications using the MVC patterns (most recent article here).

So, Silverlight Beta 2 came out and I spent some time absorbing those changes and trying to work out how they affect what I was doing. I have also made some alterations to the Silverstone framework to remove some code smells I was experiencing when wiring the Views and ViewModels together in preparing part 4 of the series.

One thing that Beta 2 adds is much better support for bubbling of RoutedEvents. This is a great change, but it actually caused a problem for my CommandManager class! The CommandManager was relying on the mouse and keyboard events bubbling up from their target element to the application root in order to provide automatic invalidation of the CanExecuteChanged handler on registered commands. Now that Silverlight has more advanced handling of these events, they no longer bubble up to the application root (as the textbox/button/whatever marks them as e.Handled=true). This is the correct behaviour and mirrors WPF, but it means my technique no longer works, making the ViewModels slightly more complex as they need to manually raise the CanExecuteChanged event.

Once Silverlight gets event tunnelling, which I'm sure (hope!) will be incorporated into the next release, I will add this back in as we will be able to capture the events before they are actually handled by the target element (e.g. PreviewKeyDown / PreviewMouseDown).

So I now have a basic view working, and will be creating the other views soon and blogging the next part in the near future.

As I mentioned, whilst working on this, I made a few refactorings to Silverstone (and to the sample code):

The Ioc Container is no longer a static class. This always bothered me - why have a static class here? So I made it a non static and also made it implement an interface (IContainer). The added bonus of this (and the real reason I did it) is that other components can access the container without going through a static reference. So, the container now registers itself with itself, and you can get it passed to your class simply by adding a constructor parameter of type IContainer.

Once I did that, I refactored the Shell class, which was looking rather nasty from the client API side of things! If you remember in Part 2 of my series, I was writing a LoginViewModel but I was having to pass the other related views into the constructor in order that I could navigate to them upon certain actions (see the comments saying This is just an empty view interface for now *shudder*). I think having to do this makes iterative development much harder as you need to create fakes and register them with the Ioc container just to have your class be constructed!

So instead, the Shell now uses the IContainer to get the views from it and all I need to do is pass the type of the View interface to the Shell and it can do everything from there, like so:

this.shell.Navigate<IFriendListView>();

Finally, I moved the entire sample code into the actual Silverstone SVN repository, which makes it much easier for me to develop the two things side by side! So if you want to an early preview of the code, you can get it from svn

I will be posting the entire solution once it's finished, and hopefully uploading it to some hosting area in the cloud.

No comments: