Tuesday, April 6, 2010

Silverlight 3 MVVM Project Part I (updated Architecture)

I know things in IT change fast, but I didn’t know things could change this fast. As soon as I posted my previous blog on the Silverlight 3 MVVM Architecture, it was already outdated. So here is the update.

We decided that because we use bindings to get a reference to the commands, the commands are actually a part of the viewmodel. So the updated architecture looks like this:


A View implements an interface, this is a change on the previous model. For a composite application I don’t want to implement a hard dependency on a specific kind of view.

For example: Let’s say I have a module that allows me to search for a person (SearchPersonModule) and I have another module that allows me to search for cars (SearchCarModule). If I want to use these modules on PersonView and CarView, I would have to specify which module I want to load (hard dependency). This means I’m using my modules as UserControls. This can be a good idea, but it defies the purpose. I’m trying to take it a step further. The SearchPersonModule and SearchCarModule both implement the same interface (Let’s call that ISearchModule). In the PersonView and CarView I now only have to specify that I want a module that implements ISearchModule and leave it up to the Application or IoC container to give me an instantiated version of the right module. (I’ll describe how this is done in the next part of this blog)

A View only has one ViewModel, everything a View needs to know is in that ViewModel (or the ViewEntities). A View can contain other Views and those Views will have their own ViewModel. The ViewModel also creates the Commands for the View, I explained how we use Commands my previous post. The ViewModel is also responsible for any view-specific functions like calculating a total sum or counting the number of persons in a search result.

A ViewModel can have zero or more ViewEntities, ViewEntities are like Data Transfer Objects, they just carry the data that needs to be presented in the View.

The Model is the place where we define the information need for the module. Let’s say I need a country list, the module will request an instance of the ICountryRepository and ask for the Country list. I don’t care what is giving me the the Country list, I just want it. The implementation of the CountryRepository is not my concern. I just know that ICountryRepository has a function List<CountryDataContract> GetAllCountries(). In the model I will map the CountryDataContract to my CountryViewEntity and expose that CountryViewEntityList as a property on the model.

The IService stands for all the service interfaces I have within my application or framework (with service interface I do not mean a web service interface). For the EventManager I have an IEventManager interface and for the PersonRepository I have an IPersonRepository interface.

All the communication to and from the module will be facilitated by the Services. All the communication within the module will be done by the commands.

The next part of this blog will describe the implementation of this architecture.