
Introduction
The best way for me to build a serious Silverlight application always has been CompositeWPF (Prism v2). This doesn’t mean that I don’t like other frameworks, but it’s just that I was familiar with the concepts in Prism. It’s been available for WPF for quite some time now and it was the first framework for Silverlight that I have come into contact with.
There are more frameworks available and I really think people deserve to know about them. Also I think trying out a different framework can be a good exercise to learn new ways to do things and to improve upon existing ideas.
Short introduction to Caliburn
In this article I will talk about an application framework called Caliburn that provides support for implementing the MVVM design-pattern in Silverlight applications.
I will be using the Silverlight version of Caliburn, but there’s also a WPF version which has 99,8% of the same features that are available in the Silverlight version. The other 0.2% of the features are WPF only, as with most application frameworks that target both Silverlight and WPF.
The sample application
All of the code demonstrated in this article comes from the TaskTracker Silverlight solution. TaskTracker offers a SCRUM-like way of setting up a planning for a software project. Once you’ve created a planning you can track the amount of hours spend through the activities feature of the application.
At this stage it’s not much more than a bunch of stubs and a pretty frontend. It is however a great way to show you some of the things you can do with Caliburn. I am however planning on releasing it on CodePlex, so that other people can use it and view its code to get ideas on how to build a larger Silverlight application.
A screenshot of what’s coming is shown below:
Setting up a project
The first thing I noticed when starting a new project trying to get Caliburn up and running was the amount of magic it does. As a developer you don’t have to do a whole lot to get a basic application up and running.
Bootstrapping
The first step to get things up and running is to create a new Silverlight application project and add a couple of references to the project. You will need a reference to the following assemblies from the Caliburn framework:
– Caliburn.Core.dll
– Caliburn.PresentationFramework.dll
– Microsoft.Practices.ServiceLocation.dll
Once the application project is created and the references are set, you can make the Silverlight application into a Caliburn application by changing the XAML within the App.xaml file to something similar to the following:
1: <cal:CaliburnApplication >="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
2: >="http://schemas.microsoft.com/winfx/2006/xaml"
3: >="clr-namespace:Caliburn.PresentationFramework.ApplicationModel;assembly=Caliburn.PresentationFramework"
4: x:Class="TaskTracker.App">
5: </cal:CaliburnApplication>
After the app.xaml file is updated you will need to change the codebehind too, so that it derives from Caliburn.PresentationFramework.ApplicationModel.CaliburnApplication. You can remove the rest of the methods that were added by Visual Studio 2008/2010, these are no longer needed.
1: namespace TaskTracker
2: {
3: /// <summary>
4: /// Application class
5: /// </summary>
6: public partial class App : CaliburnApplication
7: {
8: /// <summary>
9: /// Initializes a new instance of <see cref="App"/>
10: /// </summary>
11: public App()
12: {
13: InitializeComponent();
14: }
15: 
16: /// <summary>
17: /// Selects the assemblies for the application
18: /// </summary>
19: /// <returns></returns>
20: protected override System.Reflection.Assembly[] SelectAssemblies()
21: {
22: return new[] { Assembly.GetExecutingAssembly() };
23: }
24: }
25: }
The CaliburnApplication base class is responsible for bootstrapping your application. It initializes all the framework components required for the application to run. It does this by initializing an instance of an inversion-of-control container and setting up a ServiceLocator so that the framework components can be found by the application.
Building your first presenter
Now that the application is bootstrapped you can add screens to it. To make an effective structure you can place the views and presenters in separate folders like the following structure demonstrates:
The idea is to create a folder for a specific feature in the application and add two subfolder to it. One for the views and one for the viewmodels/presenters. For this article I’m going to show you how to create the Shell feature with the main presenter/view combination.
Once the shell folder with the views and presenters subfolders have been created, you will need to add a new class named MainPresenter to the presenters folder. This class will be the main presenter of the application. The following code snippet shows the contents of the class.
1: namespace TaskTracker.Shell.Presenters
2: {
3: /// <summary>
4: /// Main presentation component for the application
5: /// </summary>
6: public class MainPresenter : Presenter
7: {
8: 
9: }
10: }
The presenter that was just created is bound to the view by the Caliburn framework. Every property you add to the presenter will be available for databinding on the view that’s created next.
Now that you have a presenter you can add a view for it by adding a new Silverlight user control to the Shell/Views folder. It should be named MainView.xaml so that it’s automatically associated with the presenter by the Caliburn framework.
The final step in completing the basic structure of the application is to modify the App.xaml.cs file and add an override for the CreateRootModel operation. This method should return a new instance of the MainPresenter.
1: /// <summary>
2: /// Creates the root model for the application
3: /// </summary>
4: /// <returns></returns>
5: protected override object CreateRootModel()
6: {
7: return Container.GetInstance<MainPresenter>();
8: }
What will happen when the application starts, is that the MainPresenter will get fired up. After it’s loaded Caliburn will try to find a view for the presenter by replacing the .Presenters part in the namespace of the MainPresenter class with .Views and replace the …Presenter part of the class name with …View. If it finds a view in the right namespace with the right name it will automatically show the view and bind the presenter/viewmodel to it.
Now that you got a presenter and a view you can fire up the application by pressing F5 inside Visual Studio. You will end up with the application being started inside Internet Explorer (or in your favorite browser, if you’re not using IE8).
Choosing an IoC container
While not required it’s a good idea to setup a different inversion-of-control (IoC) container than the default. The default one is limited and doesn’t offer the features that e.g. Unity or any other fully fledged IoC container will have.
There is support for practically any major IoC container in the marked through the use of various adapters. I’m only going to show how to use Unity, but the same trick works also for other IoC containers.
To add support for Microsoft Unity you will need to add a reference to two additional assemblies:
– Microsoft.Practices.Unity.dll
– Caliburn.Unity.dll
Both of these assemblies are available from the directory where you extracted Caliburn.
Once you have added the reference to these assemblies you need to modify the App.xaml.cs file and override the CreateContainer method. The contents of this method are shown below:
1: /// <summary>
2: /// Creates the IoC container to use for the application
3: /// </summary>
4: /// <returns></returns>
5: protected override Microsoft.Practices.ServiceLocation.IServiceLocator CreateContainer()
6: {
7: return new UnityAdapter(new UnityContainer());
8: }
After Unity has been added to the application you will have all the default features of Unity available to you. You can use [Dependency] to let Unity inject dependencies. Caliburn will work transparently with the Unity container, so there’s no additional coding required to get things up and running.
View-first or Model-first development?
In the Building your first presenter section I demonstrated the use of the model-first approach with Caliburn. This is the recommend mode for working with Caliburn. The model-first approach works by loading models first instead of views. The views will be managed automatically by the framework.
Personally I think that this model works pretty good. There is however a downside to this. Designer won’t like what is done to the views when you start to compose views. When you need to load a child view you will need to add a View.Model attached property to the view like the following snippet:
1: <layoutToolkit:TransitioningContentControl Margin="12,6" cal:View.Model="{Binding CurrentPresenter}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>
This enables Caliburn to resolve the view for the provided model and add it as a child to the ContentControl. I used the transitioning content control, but this also works for the default ContentControl in Silverlight. Expression Blend doesn’t like this kind of markup and you will not be able to configure this through any user interface option in Expression Blend. This isn’t a real issue for developers, but it isn’t as userfriendly for designers as you might like.
The advantage of a model-first approach is the possibility for developers to build and test the model for the views using automated tests without having a view attached to it. And because Caliburn is used there’s no real connection between the view and the model, so the designer can happily design the view in Expression Blend, without having to worry about problems loading the views onto the design surface. Keep in mind though that databinding needs to be done using custom expressions, so some additional knowledge of the binding expression language is required.
An alternative to the model-first approach in Caliburn you might want to go View first. This model is characterized by the fact that the view is instantiated first and the model is attached to it after the view is loaded.
The view in a view-first design refers to a model by setting it’s datacontext property in XAML to the model. This works great in Expression Blend, because the designer can simply select the model from a dialog and bind it to the view as the following screenshot demonstrates.
Depending on the designer croud on the team you may have to consider this an option, but keep in mind that Caliburn may not really play along when using this pattern. After talking to Rob Eisenberg (The head-master-chief builder of Caliburn) he recommended me going with the model-first approach, but I still think it should be noted that the view-first approach is there and that you can use it. However if you are thinking about using the view-first approach, I suggest that you abandon Caliburn and go for CompositeWPF. The CompositeWPF supports view-first a lot better, since it doesn’t as much magic for you as Caliburn is doing.
Actions, commands and other ways to hookup logic
Now that you have a presenter and a view you will need a way to hookup behavior from the presenter to the view. Within Caliburn this is done by using Actions or Commands.
Using actions to bind presenter methods to the view
Actions are implemented using methods on the presenter. This can be any method that returns either nothing (void) , an IResult or an IEnumerable<IResult>. If you want more information in the IResult model for Caliburn I suggest you check out the documentation on how to use it.
The first step in setting up an action and binding it to the view is to define a method that will execute a piece of behavior. As an example I have created a simple method that shows a messagebox.
1: public void ShowMessage()
2: {
3: MessageBox.Show("This is a messagebox");
4: }
To bind this method to the user interface you will need to add a XML namespace reference to the view XAML file that looks like the following snippet:
1: <UserControl >="clr-namespace:Caliburn.PresentationFramework;assembly=Caliburn.PresentationFramework">
2: <!-- View content -->
3: </UserControl>
After adding the XML namespace reference to the XAML file you can bind the method using a special action markup language by creating a button that looks like this:
1: <Button Content="Click me" Width="75" Height="24" cal:Message.Attach="[Event Click = Action ShowMessage]" />
The cal:Message.Attach property tells the framework that we want the Click event of the button to be bound to the DisplayMessage method in the presenter. You can also bind other events, by providing their name instead of the Click event.
For more information on how to use actions I suggest you take a look at the documentation. It shows a lot more details on how to setup actions in various situations: http://caliburn.codeplex.com/wikipage?title=Action%20Basics&referringTitle=Documentation
Commands in Caliburn
The other method to bind behavior to a view is to use commands. The command design-pattern is specifically designed to build behavior as an object. To build a command you need to create a new class that contains an Execute method.
1: public class ShowMessageCommand
2: {
3: public void Execute()
4: {
5: MessageBox.Show("This is a command driven messagebox");
6: }
7: }
You can use the same syntax to bind the command to the user interface as is used to bind actions to the user interface. The following snippet demonstrates how this works:
1: <Button Content="Click me" Width="75" Height="24" cal:Message.Attach="ContainerCommand ShowMessage" />
Before the command is actually going to work you need to register it as a Singleton instance with the IoC container in the application. This is best done in the App.xaml.cs class, by extending the CreateContainer method with a snippet that looks similar to the following:
1: /// <summary>
2: /// Creates the IoC container to use for the application
3: /// </summary>
4: /// <returns></returns>
5: protected override Microsoft.Practices.ServiceLocation.IServiceLocator CreateContainer()
6: {
7: var container = new UnityContainer();
8: container.RegisterInstance("ShowMessage",new ShowMessageCommand());
9: return new UnityAdapter(container);
10: }
Personally I don’t like the way the command pattern was implemented in Caliburn. There is a standard ICommand interface available so why not use that to provide developers with a general guideline on how to implement the commands. It also saves in the Reflection department.
Combining other frameworks
Caliburn is great on its own, but some features simply aren’t there. However this isn’t a real problem since you can combine Caliburn with other frameworks to provide the additional features required.
By default there’s support available to integrate Caliburn with MEF (Managed Extensibility Framework) and CompositeWPF, so if you’re missing critical features in the modularity department or need to use event aggregation, you can always add a reference to either MEF or CompositeWPF to extend the Caliburn features with the additional features contained in both of these frameworks.
Note: MEF is only available for .NET framework through download or by installing .NET Framework 4. You will need Silverlight 4 if you want to use it from inside a Silverlight application.
Final thoughts
Caliburn is a framework that can be usable when you don’t need the modularity support that is included with CompositeWPF. There are however still some things that might be to your liking. I’ve had one of those moments with the Command support in the framework and had to include some classes from the CompositeWPF framework to solve the problem with the Command support in Caliburn.
The framework sometimes does a little too much magic for my liking. It doesn’t really show you what’s going on under the hood. This makes debugging things when there’s a problem rather hard. I have good hopes however that the problem will be fixed in version 2, which is in the works right now.
Because there is so much magic, it’s recommended to download the source and compile it yourself. That way you can debug the code and see for yourself what is going on. It’s also the best way to learn to apply the various components in the framework in an effective manner.
– The download for the framework can be found here: http://caliburn.codeplex.com/releases/view/34985
– Check here for documentation and sample: http://caliburn.codeplex.com/documentation
– More information on Unity can be found here: http://www.codeplex.com/ unity