First steps with Caliburn Micro in Windows Phone 8 – The first project

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

  1. The theory
  2. The first project
  3. Actions
  4. Collections and navigation
  5. Tombstoning
  6. Advanced navigation and deep links
  7. Messaging
  8. Using launchers and choosers
  9. Use your own services
  10. The Application Bar
  11. Pivot
  12. Lazy loading with pivot
This entry was posted in Windows Phone and tagged , . Bookmark the permalink.

34 Responses to First steps with Caliburn Micro in Windows Phone 8 – The first project

  1. ArchieCoder says:

    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

    • qmatteoq says:

      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.

  2. Daniel says:

    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.

  3. Daniel says:

    Agghhh.. darn c# template! 😀 Thanks man. And kudos on some great articles.

  4. at says:

    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?

    • qmatteoq says:

      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 says:

        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();

        • qmatteoq says:

          Do you have the chance to upload your project and send me the link? This way I can take a look

          • at says:

            I uploaded the project to:
            https://jumpshare.com/b/gNKUOY6KyBCGP4oQ5WV5

            Thank you!

          • qmatteoq says:

            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
            {
            ///

            /// Constructor for the Application object.
            ///

            public App()
            {
            // Global handler for uncaught exceptions.
            InitializeComponent();
            }
            }

          • at says:

            Yes that worked! I should have read your post more carefully. Thanks for your generous help and great posts!

      • at says:

        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]

  5. Krystian says:

    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?

  6. michal says:

    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

  7. michal says:

    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

  8. Yun says:

    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

    • qmatteoq says:

      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.

  9. Rasmus says:

    Hi there. Great tutorials. Can you please upload the project for this sample? I’m having some strange errors (TargetInvocationException)

    Thanks a bunch!

  10. Chris says:

    Hi, Great article. Any chance of turning it into a Visual Studio Project Template?

Leave a Reply to Krystian Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.