I’ve got some criticism from Alex Golesh in a comment on one of my latest Posts (Managing Silverlight resources contained in external assemblies), First I would like to thank him for taking his time and writing this comment, I would like to reply him with this post.
First let’s see Alex’s Comment:
I have to comment it, because the code lead to bad practice...
First, it heavily assumes you have all you assemblies in single XAP package - which is a bad practice for "heavy" Silverlight applications and especially real MVVM based applications.
Second, XamlReader will throw an exception if you resource (XAML) have a refernces to external resource dictionaries.
Last, but not least, this code will not work in SL3 and Silverlight for Windows Phone 7.
Regards,
Alex
Alex’s first point is what really made me write this following post, but I will get to it later. His second point is just plain wrong, I’ve created a small sample proving it, it is not very interesting sample as it self in my opinion but I just don’t want you, dear reader, to refrain from this solution on basis of Alex’s false assumption. You can download it here.
About Alex’s last point, It might be that it will not work in SL3, I’ve not tried to test it on that SL version, Even how I wouldn’t recommend you developing RIA in SL3. About Windows Phone, I reckon that on the Phone platform a different approach is needed to be used, the code to manage resources is used when writing decoupled modules should be tuned to the platform specific needs. Anyway it is out of scope from this post, I will leave it for future post.
Now, let’s talk about Alex’s first point, it really boiled my blood
, an assumption so wrong, I’ve not heard for a long time, the whole purpose of that post was to allow you writing separate modules (which every module comes as his own XAP package) by keeping resources separate as well in order to refrain from tight coupling it in the first place. Now what really made me laugh is that each resource dictionary usually contains DataTemplates which pair a view and its ViewModel, an essential phase for maintaining MVVM
.
In Alex’s defense, he could have never known the full picture, how does that one piece of the puzzle fits in a larger picture.
That large picture is what I mean to present here.
Let’s get started with Developing MVVM Silverlight App
First of all, I will be using Prism 2.2, as I’m writing this post, it is a the release version of Prism.
I will be following Prism’s guidance, as I truly believe in it and my experience with it from the day it was born has been very successful. I’ve started developing Prism with WPF and when I’ve made a switch in Silverlight I’ve tried to maintain the same methods of implementation. I will be covering some of Prism main features in this post so a knowledge in Prism is very useful.
You better download the sample now, as I will be explaining it, and it might be easier for you to follow with that code in front of you. You can download it here.
The solution contains:
- 3rd Party folder: we will keep compiled assemblies such as Prism’s assemblies, other controls vendors assemblies.
- Client folder: we will keep projects related to our client, such as Modules and Common projects referenced by all modules.
- Silverlight Main Project: It contains the Shell view, we will inject views into it.
- ASP.Net Main Host: For this sample purpose it will be the default generated host you got from the Visual Studio Wizard.
Let’s investigate the Common project: This project is referenced by all modules, and must not reference any other project. I kept it as minimal as possible so it will contains only essential items for this sample to function.
Let’s see my version of ViewModelBase, it appears everybody got one
.
public class ViewModelBase<T> : ViewModelBase
{
public new virtual T Model
{
get { return (T)base.Model; }
set { base.Model = value; }
}
protected override void ModelChanged()
{
OnPropertyChanged(() => Model);
}
}
I find it convenient that when I am binding a ViewModel to a View, I always got a Model property to use, making it reoccurring pattern to follow, and it will not constrain you in any way, we will see it in use soon.
public class TemplateContentControl : ContentControl
{
protected override void OnContentChanged(object oldContent, object newContent)
{
base.OnContentChanged(oldContent, newContent);
if (newContent is UIElement) return;
string key = newContent.GetType().Name;
ContentTemplate = (DataTemplate)Application.Current.Resources[key];
}
}
This is an interesting piece of code, it’s main purpose is to replicate WPF’s DataTemplate DataType ability. When we add a ViewModel to the SL’ visual tree, this control is going to grab the relevant DataTemplate.
public class RegionNames
{
public const string MainRegion = "MainRegion";
public const string LowerRegion = "LowerRegion";
}
Regions are a fundamental feature of Prism. which allow you to specify a place-holder inside a view, and let another view get placed in that place-holder without really knowing where is that place-holder location on the screen and in it’s project, thus decoupling a view from it container.
In this specific sample I’ve also located here the Model of the application, usually it deserve a separate project, but in order to keep things more simple I’ve placed it in here.
We have finished browsing through the Common project, now let’s move forward to talk about Modules.
Modules are pieces of application functionality that are suppose to behave autonomously. How do you define Modules in your app, it is actually a difficult question to answer. It really does depend on various architectural considerations.
In this sample app we will maintain 2 separate modules, communicating between modules is an important matter that I will have to leave for future post.s To keep this sample simple, the 2 modules do not interact with each other.
In Silverlight scenario each Module is in fact a Silverlight Application template (and not a Silverlight class library), after it’s creation you can delete all the files being generated. Make certain that in your ASP.net Host, it expects it’s XAP from the Silverlight Applications Tab.

Each module follow a certain skeleton structure:
- [Name]Module.cs : an entry point which we will be called when our modules are loaded.
- Views : a folder which will hold all relevant views of a Module.
- ViewModels: a folder which will hold all relevant ViewModel of a module. every View got a ViewModel (but not every ViewModel got a view).
- Resources: a folder to hold a specific resources needed by that (and only that) module such as images and Resource Dictionaries. Atleast one ResourceDictionary I recommend to maintain.
Let’s see the entry point of a module.
public class PatientsModule : IModule
{
private readonly IUnityContainer _container;
private readonly IRegionManager _regionManager;
public PatientsModule(IUnityContainer container, IRegionManager regionManager)
{
_container = container;
_regionManager = regionManager;
}
public void Initialize()
{
RegisterResources();
_regionManager.AddToRegion(RegionNames.LowerRegion, _container.Resolve<PatientsViewModel>());
}
private static void RegisterResources()
{
Assembly assembly = Assembly.GetExecutingAssembly();
string assemblyName = assembly.FullName;
string[] nameParts = assemblyName.Split(',');
var dictionary = new ResourceDictionary();
StreamResourceInfo resourceInfo =
Application.GetResourceStream(new Uri(
nameParts[0] + ";component/Resources/ModuleResources.xaml", UriKind.Relative));
var resourceReader = new StreamReader(resourceInfo.Stream);
string xaml = resourceReader.ReadToEnd();
var resourceTheme = XamlReader.Load(xaml) as ResourceDictionary;
Application.Current.Resources.MergedDictionaries.Add(resourceTheme);
}
}
First you will notice it contains the piece of code that started the whole issue (
) but now in context. Note that it got a few basic stuff injected to it such as Unity (IoC Container) and RegionManager.
The initialize is in fact the method that will get called once a module is loaded. In this case create a new instance of a specific ViewModel (using Unity’s Reslove) and using the RegionManager we inject it to the MainRegion place-holder. Complicated? perhaps but it will grow on you once you get use to it
.
Note that by passing to the RegionManager a non-visual object we are depending on DataTemplates to tell Silverlight how to render that kind of an object. This is where our Resource Dictionaries and TemplateContentControl come into place.
Let’s see an example of a ViewModel.
public class PatientsViewModel : ViewModelBase<IEnumerable<Patient>>
{
public PatientsViewModel()
{
Model = new List<Patient>
{
new Patient {FullName = "Margol Raz"},
new Patient {FullName = "Jim Brown"},
new Patient {FullName = "Lazy Fox"}
};
}
}
Note that by deriving from ViewModeBase we got a Model property of type IEnumerable<Patient> we can make use. For the sake of a simplicity I’m just filling it up with some data. Usually you get it from a service or other means of persistency.
Now let’s check out a View
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<ListBox ItemsSource="{Binding Model}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock FontSize="16" Text="{Binding FullName}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
We can clearly see we databind to the Model property of the ViewModel.
We have gone over some very important aspects but how the ViewModel get hold of it’s View? It all depend on the ResourceDictionary.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
xmlns:Views="clr-namespace:Patients.Client.Modules.Patients.Views;assembly=Patients.Client.Modules.Patients">
<DataTemplate x:Key="PatientsViewModel">
<Views:PatientsView/>
</DataTemplate>
</ResourceDictionary>
A very important points to remember here:
- It is important to keep the key of the resource the same type name of the ViewModel otherwise the TempalteContentControl will not be able to locate it.
- You must specify the full namespace of the views even though it is in the same project (working around a possible bug).
- The most important thing to remember his the that Silverlight (and WPF in that prespective) will push the ViewModel to the DataContext of the View, this is how DataTemplates are functioning, and this is why DataBinding are easy as a breeze in MVVM and in my purposed way of implementing it.
Our 2nd Module is very similar and will not cover it in here. It is just to prove Alex we still keep are apps in good code practice
.
Our last project we will go over together is the Shell project. It contains a Bootstrapper class that is doing the Prism heavy lifting in the startup of the application, reading the configuration file, loading up the modules, setting up Unity Container and RegionManager, etc.
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="50*"/>
<RowDefinition Height="50*"/>
</Grid.RowDefinitions>
<com:TemplateContentControl Regions:RegionManager.RegionName="MainRegion" />
<com:TemplateContentControl Grid.Row="1" Regions:RegionManager.RegionName="LowerRegion" />
</Grid>
This is our Shell, all it contains is the placeholders for the modules to inject their ViewModels. note the usage of TemplateContentControl.
Conclusion
We have covered a lot of stuff today.
We have gone through creating a small sample in MVVM, Prism and I hope now it will be up to the high standards of the Silverlight Community.
Ariel