Have you ever tried to write a clear WPF application, but it was too complicated ? Caliburn Micro solves your problem. Caliburn micro is small yet powerful framework, designed for building WPF applications. Framework support for MVVM patterns will enable you to build a solution quickly.

Getting started

To start working with the Caliburn Micro you should create a WPF project and add reference to the Caliburn.Micro.dll and the System.Windows.Interactivity.

Install-Package Caliburn.Micro

After installation you need to remove MainWindow.xaml and an attribute from App.xaml. App.xaml will look like this now:


<Application x:Class="CaliburnMicroTutorial.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Application.Resources>

  </Application.Resources>
</Application>

View Model

Caliburn Micro promotes a View-Model-First approach, so the next step is to add a class to represent the view model.

  public class TestViewModel : PropertyChangedBase
  {

  }

Caliburn Micro expects a particular naming convention. Each name should end with 'ViewModel'. There is another condition - each class should extend the PropertyChangedBase class. It provides implementation of INotifyPropertyChanged interface, and allows to raise property change notifications. Currently view model does not do anything, in the next step we will add view and extend the functionality.

View

In this step, we create a view for the previously created view model. As I mentioned, Caliburn Micro expects a particular naming convention. Each view should end with 'View' and start with the same name you used for the view model. In our case we should add UserControl.xaml named 'TestView', and set the dimensions of the window.

<UserControl x:Class="CaliburnMicroTutorial.TestView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
  <Grid Width="500" Height="500" Background="LightBlue">

  </Grid>
</UserControl>

Bootstrapper

The bootstrapper is the most important class in the application. It is also a place where you can configure the framework for the needs of your application. As an example I present a minimalist version of the Bootstrapper for Caliburn.Micro version 2.0.1. I presented absolute minimum necessary to operate the application.

public class AppBootstrapper : BootstrapperBase
{
    public AppBootstrapper()
    {
        Initialize();
    }

    protected override void OnStartup(object sender, StartupEventArgs e)
    {
        DisplayRootViewFor<TestViewModel>();
    }
}

The OnStartup method is to define the starting point of application. The last step is to tell the application to use the bootstrapper. This is done by adding your bootstrapper to a resource dictionary in App.xaml. After doing this, App.xaml will look like this:


<Application x:Class="CaliburnMicroTutorial.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:CaliburnMicroTutorial"
             >
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary>
                    <local:AppBootstrapper x:Key="bootstrapper" />
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Now, we can run our project. We should see:

Empty Application

Data Binding and Events Handling

We have just written a very simple application that actually does nothing. Now is time to add life to our application. For example, we will return string value from view model and we will display it on the view.

Data Binding

Data binding allows us to connect view with view model. Our goal is to display the value passed from view model on the view. In the first step, we need to define a property in the view model.


    public class TestViewModel : PropertyChangedBase
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                NotifyOfPropertyChange(() => Name);
            }
        }
    }

As you can see, inside the setter we need to call NotifyOfPropertyChange method. It allows to perform property change notifications, what will refresh value displayed on the view.

In the second step, we should add text box control to the view, with binding to chosen property in view model.


<UserControl x:Class="CaliburnMicroTutorial.TestView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid Width="500" Height="500" Background="LightBlue">
       <TextBox FontSize="40" HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Name}"></TextBox>
    </Grid>
</UserControl>

There are two possibilities to bind control with a view model:

  • Conventions: Text property from TextBox control will be automaticly bind with property in view model but TextBox name has to be the same what property in view model.
            <TextBox FontSize="40" HorizontalAlignment="Center" VerticalAlignment="Center" Name="Name"></TextBox>
  • Manual binding: We need to manualy indicate property in view model ( Example above ).

I prefer the second possibility, because it clearly shows bindings between view and view model. For the first approach, when we have dozens controls in view, we can get lost.

When we run application we should see:

Application With Value

Ok, now we have working application, displaying hardcoded value from view model. Now we have to add action to our application. Next, let's work on adding a button that changes the displayed value. The simplest solution is hook up the click event of a button to an event handler in the view model. First, we should add the method in the view model:


    public class TestViewModel : PropertyChangedBase
    {
        private string _name = "Philip";
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                NotifyOfPropertyChange(() => Name);
            }
        }

        public void NameChanged()
        {

        }
    }

Now add a button to view and include the xmlns:cal="http://www.caliburnproject.org" namespace:


<UserControl x:Class="CaliburnMicroTutorial.TestView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:cal="http://www.caliburnproject.org" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid Width="500" Height="500" Background="LightBlue">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
       <TextBox HorizontalAlignment="Center" 
                VerticalAlignment="Center"
                Name="TextBoxControll" 
                Text="{Binding Name}"
                FontSize="40"
                Grid.Row="0"
                ></TextBox>
        <Button Grid.Row="1" FontSize="30" cal:Message.Attach="[Event Click] = [Action NameChanged]">Click Me</Button>
    </Grid>
</UserControl>

Also like in example above, there are two possibilities to define event binding between view and view model.

  • Conventions: Button has to be named as the method in the view model.
    <Button Name="NameChanged" Grid.Row="1" FontSize="30" >Click Me</Button>
  • Manual binding: We need to manually indicate handler ( Example above ). Additionally when we define the handler manually, different parameters can be passed to the method like this:
    <Button Grid.Row="1" FontSize="30" cal:Message.Attach="[Event Click] = [Action NameChanged($dataContext, TextBoxControll.Text)]">Click Me</Button>

You can find more information about hooking up events using Caliburn Micro from the documentation.

Ok, after we have defined button and handler we can add logic that will change displayed string value after each click.

        public void NameChanged()
        {
            Name = NameGenerator.Generate(Gender.Male);
        }

In example I used RandomNameGenerator

Ok, now run application and enjoy.

Application with button

Example you can download from git hub

This is a very small demonstration of the possibilities offered by the Caliburn Micro. I encourage everyone to familiarize oneself with this framework. In part 2 I will describe more advanced usage of the Caliburn Micro. See you soon!

About the author:

Filip Paluch

Versatile software developer in BT Skyrise, specializes in .NET, but he is also keen on javascript, html and many more technologies. Filip is a teamplayer and clean code enthusiastic. Code review with him is always a journey which help you learn a lot. Privately, a lover of travel.

Next Post Previous Post

blog comments powered by Disqus