Tuesday 9 February 2010

Fixing Blendability issues

Hardly a real word, but Blendability is quite an important issue you will need to address if you work on a large project and/or if a designed is involved. Currently, I do not have the luxury of a designer and have not yet got a Blend license so most (all?) my XAML Pages/UserControls where... umm Unblendable :-) This is evident in this previous post. But one should never shy away from fixing a problem so here is a fix, following from the previous post.

Differentiating behavior if in design mode

The following idea was inspired by one of many blendable View-ViewModel examples out there. It is evident that in order to get the VS designer and Blend to accept our ViewModel, we will need to allow XAML to get a concrete instance of it during design mode. Lets start with a simple way of determining if we are in design mode. In the ViewModelBehavior class:



Now, in the ModelAttached handler we can use the above method to resolve an instance of the ViewModel both at design and run time:



But how do create a concrete instance of a ViewModel class?

At this stage, the DependencyPropertyChangedEventArgs args parameter will contain the fully qualified type of the interface of our VM. The catch here is to make an assumption. All VM interfaces (e.g. IResourceListViewModel) have a corresponding concrete class (e.g. ResourceListViewModel) within the same namespace. If this is not the case you will have to find a different way of creating instances of VMs that implement your interface. So AttachDesignTimeModel looks like this:



The body of the method is very similar to the action assigned to the closure from within our bootstrapper (which will be executed at runtime). Using a simple LINQ query, the type of the VM is resolved and a new instance is created. There is 1 more catch here, the VM must have a public parameterless constructor defined, in order for Activator.CreateInstance to be able to create an instance at design time.

And this is it!

If you build your solution and open a view which uses the above behavior to create and attach a VM it should work fine both at run and design time. Not bad even though there are 2 catches:


  1. VM classes need to be located in the exact same namespace like the interface they implement.

  2. The VM needs a parameterless public constructor (only used during design time).



And another thing...

This all works well but the check on the design mode can lead you into trouble in a high volume production environment as the folks over at CSLA have discovered. Since it is unnecessary overhead anyway, you can wrap the whole code in the DEBUG compiler directive to only have active during development:



Happy designing!

No comments:

Post a Comment