In the previous post we’ve seen the theory behind the Caliburn Micro project and why is different from other toolkits (like MVVM Light) that are available to implement the MVVM pattern in a Windows Phone application.
In this post we’ll start to do some practice and we’ll see how to create an application with the MVVM pattern that uses the Caliburn Micro framework.
UPDATE: the section of this post about using the naming convention to link the View and the ViewModel has been updated, to address an issue I included in the previous version of the post. Views and ViewModels should be created inside a specific namespace.
Create the first project
First you’ll have to create a new Windows Phone project (7.5 or 8 is the same for the moment, Caliburn Micro supports both) and, using NuGet, add the Caliburn.Micro library: NuGet will take care of satisfying all the needed dependencies.
The first step when working with Caliburn Micro is to setup the bootstrapper, which is the class that will take care of creating all the needed infrastructure so that all the conventions and helpers available can work correctly. To do this, simply create a new class which should inherit from the PhoneBootstrapper class, like in the following sample:
public class Bootstrapper : PhoneBootstrapper { PhoneContainer container; protected override void Configure() { container = new PhoneContainer(); container.RegisterPhoneServices(RootFrame); container.PerRequest<MainPageViewModel>(); AddCustomConventions(); } static void AddCustomConventions() { //ellided } protected override object GetInstance(Type service, string key) { return container.GetInstance(service, key); } protected override IEnumerable<object> GetAllInstances(Type service) { return container.GetAllInstances(service); } protected override void BuildUp(object instance) { container.BuildUp(instance); } }
This sample is a standard bootstrapper for Caliburn Micro: unless you need to do something special, like registering some custom conventions, you can basically copy and past this code in your every application. The only thing you’ll have to change is the ViewModels registration: inside the Configure method you’ll have to register in the built in dependency injection container every view model and every service you’re going to use in your application. In this example, we’re going to register the class MainPageViewModel using the PerRequest method: this means that, every time the application will require a MainPageViewModel object, we will get a new instance of the class.
UPDATE: In Caliburn Micro 1.5.2 there was a breaking change in the boostrapper’s definition: previously, the RootFrame was passed as parameter of the PhoneContainer class, while now it’s required as parameter of the RegisterPhoneServices() method.
Now we need to initialize the bootstrapper: in Windows Phone we simply do that by adding it as as resource in the global application resources in the App.xaml file.
<Application x:Class="CaliburnMicro.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:caliburnMicro="clr-namespace:CaliburnMicro"> <!--Application Resources--> <Application.Resources> <caliburnMicro:Bootstrapper x:Key="bootstrapper" /> </Application.Resources> </Application>
This how it looks like a standard App.xaml in a Caliburn Micro application. Since the bootstrapper takes care of initializing everything needed by the Windows Phone application, not just the stuff required by Caliburn Micro, we can clean also the App.xaml.cs. This is how it will look like in the end:
public partial class App : Application { /// <summary> /// Provides easy access to the root frame of the Phone Application. /// </summary> /// <returns>The root frame of the Phone Application.</returns> public static PhoneApplicationFrame RootFrame { get; private set; } /// <summary> /// Constructor for the Application object. /// </summary> public App() { // Standard XAML initialization InitializeComponent(); // Show graphics profiling information while debugging. if (Debugger.IsAttached) { // Display the current frame rate counters. Application.Current.Host.Settings.EnableFrameRateCounter = true; // Show the areas of the app that are being redrawn in each frame. //Application.Current.Host.Settings.EnableRedrawRegions = true; // Enable non-production analysis visualization mode, // which shows areas of a page that are handed off to GPU with a colored overlay. //Application.Current.Host.Settings.EnableCacheVisualization = true; // Prevent the screen from turning off while under the debugger by disabling // the application's idle detection. // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run // and consume battery power when the user is not using the phone. PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled; } } }
We’ve removed every other initialization, since it’s not needed anymore: the bootstrapper will take care for us.
Now we are ready to start developing our application! In this first sample we’ll simply show some stuff on the screen and read the input of the user, just to familiarize with the conventions exposed by the toolkit.
Linking the View with the ViewModel
As already anticipated in the previous post, there’s no need to manually connect the View and the ViewModel: is it enough to use a specific naming convention and Caliburn Micro will take care for you. The naming convention is the following: the ViewModel of a View will have the same name of the View plus the ViewModel suffix. Plus, you should follow also a naming convention for namespaces: the ViewModels should be created inside the ViewModels namespace, while the Views should be stored inside the Views namespace. Typically this goal is reached by creating two separate folders, called ViewModels and Views, in your Visual Studio project. Let’s see how it works with a real example: as for every standard Windows Phone project, you should already have a view called MainPage.xaml, which is the first one that is loaded when the application starts. Delete it, since we’ll need to create a new to follow the required naming convention.
Create a new folder inside your project called Views and create a new MainPage.xaml file inside (just choose one of the available templates for creating a Windows Phone page). Remember also to open the manifest file and, in the Application UI tab, change the NavigationPage field to point to the correct main page (for example, /Views/MainPage.xaml): otherwise, the application will crash at startup because it will try to launch a page that doesn’t exist.
Now let’s create a folder ViewModels in your project and, inside it, let’s add a new class, called MainPageViewModel. As you can see, the name of the class is the same of our view (MainPage), plus the ViewModel suffix. Now let’s do an experiment: in the MainPageViewModel class simply add a public constructor and, inside, show a message using a MessageBox.
public class MainPageViewModel { public MainPageViewModel() { MessageBox.Show("I'm the MainView!"); } }
Now press F5 and start the debug in Visual Studio: voilà, you’ll see the message on the emulator’s screen! Here is the magic of the naming convention in action: since the view model has the same name of the view plus the ViewModel suffix, the view model is automatically set as DataContext of the View. This way, when the view is displayed, the ViewModel is automatically initialized and the public constructor, as it happens for every class, is called.
Important! The naming convention’s magic make sure that view and view models are automatically connected, but it still requires you to define which are the view models available in your application, by registering them in the dependancy container in the Configure method of the bootstrapper, as we have seen in the beginning of the post. This means that if we’re going to add more views and view models to our application, we’ll have to remember to register them in the bootstrapper.
Show some properties
A ViewModel without properties it’s basically useless: let’s add a property and display it in the page. The first thing to do is to start using some of the helpers that are available in Caliburn Micro: by inheriting our view model from the class PropertyChanged base we’ll have an easy way to support the INotifyPropertyChanged interface and to declare our properties to that, every time we change their value, the controls that is are binding with them are automatically refreshed to display the new value.
Here is how to define a sample property using this mechanism:
public class MainPageViewModel: PropertyChangedBase { public MainPageViewModel() { Name = "Matteo"; } private string name; public string Name { get { return name; } set { name = value; NotifyOfPropertyChange(() => Name); } } }
We define a property called Name and, in the setter, we call the NotifyOfPropertyChange method (provided by the toolkit) to notify the controls that something is changed. In the constructor, we simply assign a value to this property. Now we need to display it. In a standard application, we would put the Name property in binding with the Text property of a TextBlock, like in the following example:
<TextBlock Text="{Binding Name}" />
With Caliburn Micro this is not needed because, again, we have a naming convention for binding: the name of the control (the value of the x:Name property) should match the name of the property in the view model. In our sample, we need simply to do this:
<TextBlock x:Name="Name" />
If we launch again our application in the emulator you’ll see that the text Matteo will be displayed in the TextBlock we’ve placed in the XAML.
If you don’t like using naming conventions, you can always use the standard approach: since the ViewModel is set as DataContext of the view, as with every other MVVM based application, you can use also the standard syntax with the Binding markup extensions, as we’ve seen in the first sample.
Actions, tombstoning, messaging and a lot more
There are a lot more scenarios that we haven’t faced yet. We’ll start from the next post by seeing how to manage actions and commanding using Caliburn Micro.
The Caliburn Micro posts series
Hello!
Great series, I like your writing skill!
The clean App.xaml.cs seems too good to be true! Is declaring the Bootstrapper in the XAML enough to handle the Fast App Resume feature on WP8? I know that there is a lot of weird code to put to support the Fast App Resume normally.
Thank you
ArchieCoder
Hi Archie,
at the moment, unfortunately, the answer is no: you still need code in the App.xaml.cs to manage Fast App Resume. But it’s definitely a really interesting scenario: as soon as I’ll have some free time, I’ll try to see if it’s possible to support Fast App Resume using Caliburn Micro without having to write code in the App.xaml.cs.
The guide doesn’t seem to work anymore. Following every step and after hitting f5 for the simple MessageBox, it isn’t being called. All files in the right folders and namespaces.
do you have the chance to send me the sample project you’re working on? as far as I know nothing has changed, so the tutorial is still valid
Indeed, you should be able to download it here: https://jumpshare.com/b/5TXmsiJnQlmhAXbYFuOH
Hi, the issue is that the ViewModel class should be declared as public, otherwise it can’t be resolved by the boostrapper’s container.
So, the declaration of the class should be:
public class MainPageViewModel
{
//your class here
}
instead of
class MainViewModel
{
//your class here
}
Agghhh.. darn c# template! 😀 Thanks man. And kudos on some great articles.
I attempted to initialize the bootstrapper in App.xaml and gor error ‘Object reference not set to an instance of an object. Am I missing something?
Hi, are you getting this error just at design mode or also at runtime? If it’s the first case, it’s a known issue, see here: http://caliburnmicro.codeplex.com/workitem/307. But it’s just a design time issue, the app works fine at runtime.
at run time I am getting the error as well in below code “InitializeComponent();”. Can you please help? I am following your instruction and I am using Caliburn.Micro 1.5.1.0
public App()
{
// Standard XAML initialization
InitializeComponent();
Do you have the chance to upload your project and send me the link? This way I can take a look
I uploaded the project to:
https://jumpshare.com/b/gNKUOY6KyBCGP4oQ5WV5
Thank you!
Hi, the issue is that you have to remove everything from the App.xaml.cs, except for the initialization. In fact, the bootstrapper replaces the App.xaml.cs, by initializing everything is needed not just to use Caliburn, but also to use the application. The App.xaml.cs should look like this:
public partial class App : Application
{
///
///
public App()
{
// Global handler for uncaught exceptions.
InitializeComponent();
}
}
Yes that worked! I should have read your post more carefully. Thanks for your generous help and great posts!
The runtime error is:
A first chance exception of type ‘System.Windows.Markup.XamlParseException’ occurred in System.Windows.ni.dll
Cannot create instance of type ‘Microsoft.Phone.Shell.PhoneApplicationService’ [Line: 18 Position: 23]
The error means that there’s something wrong in the XAML definition
Thanks
Hi. I got such an error: the name “Bootstrapper” does not exist in the namespace “clr-namespace:CbMicro.WP7”. My code:
How to deal with it?
I got CM 1.5.2
Hi, actually it’s just a designer issue, the app will compile and run just fine. However, it’s a know issue, here you can see a workaround: http://caliburnmicro.codeplex.com/workitem/307
Okay, I did that, but now when I debug the MessageBox doesn’t show. And I put a Debug.Writeline inside the constructor, but nothing goes on the output. Could you provide your whole solution or something like?
Check that the constructor of your ViewModel is public. You can find a sample solution attached to the second post of the series: http://wp.qmatteoq.com/first-steps-with-caliburn-micro-in-windows-phone-8-actions/
Hi, I have similar problem with “Cannot create instance of type ‘TaskManagerv2.Bootstrapper’ I think that I checked all class and every think is ok (I hope that I didn’t miss anything). Maybe anyone can help? My app class include only Initializecomponent so it should be ok. I work on VS 2012 and want to create app for WP7.1. My source code http://jmp.sh/b/Tuj7u2TJCfVRBAXE2W95
Hi, is the problem just in design time and the app runs fine or do you have issues also while building the project?
I have this problem only when I deploy application, on Initialize method. Build process is ended without problems, but in app.xaml I have error that parameter cannot be null, parametername: rootFrame.
If the app builds fine, probably it’s just a design time issue which is already known. It’s explained with a workaround here: http://caliburnmicro.codeplex.com/workitem/307
I have this problem on the app run, build process is completed without problem. But I forgot to add that in app.xaml file I have error “Value cannot be null, Parameter name: rootFrame”, but it shouldn’t be a reason
HI,
I have a question on my project where the message box doesn’t show at all. I just follow your guide and can’t figure out what is the problem. Hope you can help me and really thanks for your series posts about CM. Here is the file:http://sdrv.ms/14XMEdk
Hi, the problem is that the namespace of the MainPage.xaml.cs is wrong: it should be Test.Views, otherwise the automagically naming convention to assign a ViewModel to its View doesn’t work.
O~! This is a fault to be lazy XD, I shouldn’t just drag it to views. Thanks anyway~!
Hi there. Great tutorials. Can you please upload the project for this sample? I’m having some strange errors (TargetInvocationException)
Thanks a bunch!
Hi, sure I’ll do it, in the meantime you can download the sample from the second post of the series http://wp.qmatteoq.com/first-steps-with-caliburn-micro-in-windows-phone-8-actions/. It’s pretty much the same, except that it contains also the samples about actions and commands.
Hi, Great article. Any chance of turning it into a Visual Studio Project Template?
Hi, actually there’s a NuGet package that does pretty much the same: it provides a bootstrapper and the basics view models. This is the package: http://www.nuget.org/packages/Caliburn.Micro.Start/