Using Caliburn.Micro (version 2) for WPF development.

Part 1: A simple application illustrating some basic Caliburn.Micro concepts.

This item is based on the Caliburn.Micro documentation and Silverlight example here: http://caliburnmicro.codeplex.com/wikipage?title=Basic%20Configuration%2c%20Actions%20and%20Conventions
Apart from the additions of the DisplayName and TextBox colour items I make no claim to originality of the text – it is highly based on the original Caliburn.Micro “Soup to Nuts” documentation here: https://caliburnmicro.codeplex.com/documentation. I have merely adapted the code and text to illustrate the usage of Caliburn.Micro with WPF rather than Silverlight.

The Caliburn.Micro2.Hello Application

First create a WPF Application project in C# named Caliburn.Micro2.Hello

To add the latest (v2) Caliburn.Micro via NuGet:

Tools | NuGet Package Manager

If under the Package Manager Console install using the PM> Install-Package Caliburn.Micro command otherwise in the UI Manager search for Caliburn.Micro and install the Caliburn.Micro package only.

This will, actually, install both Caliburn.Micro and Caliburn.Micro.Core as well as a number of other required dependencies under the project References.

We are now ready to modify the structure and code for MVVM and Caliburn.Micro.

Add the following three folders to the project:

Models

ViewModels

Views

These serve as locations to keep the various items neatly separate! This example is simple enough not to need them (and the original tutorial does not use them). However, it is a good practise to start including these from the beginning.

Note: From now on I will use CM as an abbreviation for Caliburn.Micro.

Because CM uses its own Views you should delete the MainWindow.xaml file and remove the StartupUri item from App.xaml (StartupUri=”MainWindow.xaml”)

Change App.xaml.cs to:

using System.Windows;

namespace Caliburn.Micro2.Hello
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
        }
    }
}

Because CM prefers a View-Model-First approach, let’s start there. Create your first ViewModel in the ViewModels folder (Add C# class) and call it MainViewModel. Use the following code for the implementation:

using System.Windows;
using Caliburn.Micro;
namespace Caliburn.Micro2.Hello.ViewModels
{
    class MainViewModel : PropertyChangedBase
    {
        string name;
        public string Name
        {
            get { return name; }
            set
            {
                name = value;
                NotifyOfPropertyChange(() => Name);
                NotifyOfPropertyChange(() => CanSayHello);
            }
        }

        public bool CanSayHello
        {
            get { return !string.IsNullOrWhiteSpace(Name); }
        }

        public void SayHello()
        {
            MessageBox.Show(string.Format("Hello {0}", Name)); //Don't do this in a real software project
        }
    }
}

Notice that the MainViewModel inherits from PropertyChangedBase. This is a CM base class that implements the infrastructure for property change notification and automatically performs UI thread marshalling.

There is a string property, Name, which uses CMs NotifyOfPropertyChange in set and a bool CanSayHello (read only) property which has a CM related method SayHello. SayHello just displays a MessageBox showing Name – this is for the example only – you wouldn’t want to “pollute” the view model with a UI “view” action in this way.

Note: The SayHallo method will become a button press action from a button named SayHello in the View. The boolean CanSayHello follows the CM convention and is used to enable/disable the button named “SayHello” in the View. These are based on standard naming conventions provided by CM.

We now need to create the bootstrapper that will configure the framework and tell it what to do. Create a new class named AppBootstrapper in the project “root” area. You can use this short item of code:

using System.Windows;
using Caliburn.Micro;
using Caliburn.Micro2.Hello.ViewModels; 

namespace Caliburn.Micro2.Hello
{
    class AppBootstrapper : BootstrapperBase
    {
        public AppBootstrapper()
        {
            Initialize();
        }
         protected override void OnStartup(object sender, StartupEventArgs e)
        {
            DisplayRootViewFor<MainViewModel>();
        }
    }
}

BootstrapperBase is a class provided by CM.

The Bootstrapper allows you to specify the type of “root view model” via the generic method (DisplayRootViewFor). The “root view model” is a ViewModel that Caliburn.Micro will instantiate and use to show your application.

Next, we need to place the AppBootstrapper somewhere where it will be run at startup. To do that, change your App.xaml to match this:

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

Note: Make sure you have removed the StartupUri (StartupUri=”MainWindow.xaml”) from the initial <Application ….> statement.

xmlns:local=”clr-namespace:Caliburn.Micro2.Hello” provides the local namespace

With our CM bootstrapper in the Application.Resources CM will do the rest of the work.

Run the application. You should see something like this:

CM2-Pt1-Image1

We have defined the ViewModel but not yet created the View to go with it.

To do this, create a new UserControl (WPF) in the Views folder with the name: MainView.xaml

<UserControl x:Class="Caliburn.Micro2.Hello.Views.MainView"
             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">
    <StackPanel>
        <TextBox x:Name="Name"></TextBox>
        <Button x:Name="SayHello" Content="Click Me"></Button>
    </StackPanel>
</UserControl>

The default control has been made a StackPanel – (you can use whichever WPF container you feel comfortable with).

Note that the x:Name items for the two controls match the names of the Property (Name) and Method (SayHello) in the MainViewModel code. It is this that CM uses to implement a convention based binding to certain actions.

Similarly, CM will look for a View with the same name as the ViewModel but without the Model part.

So for MainViewModel, CM looks for and uses a view named MainView.

Run the application and you should see something similar to:
CM2-Pt1-Image2
Type a name into the top text box and the button becomes enabled…
CM2-Pt1-Image3
Clicking the button throws up the message box:
CM2-Pt1-Image4
And we know that the system is working as we intended.

Adding a window title.

It would be quite good to give the App window a title. There’s a quick way to do this.

First, let’s make enough space to display it. In MainView.xaml set the MinWidth to 300.

d:DesignHeight="300" d:DesignWidth="300" MinWidth="300">

Then, in MainViewModel.cs add the IHaveDisplayName interface to the class declaration:

class MainViewModel : PropertyChangedBase, IHaveDisplayName

Implement the one and only property from that interface:

public string DisplayName { get; set; }

And create a simple no-parameter constructor which sets the DisplayName:

public MainViewModel()
{
     DisplayName = "My Hello App";
}

The complete class listing should now look like:

using System.Windows;
using Caliburn.Micro; 

namespace Caliburn.Micro2.Hello.ViewModels
{
    class MainViewModel : PropertyChangedBase, IHaveDisplayName
    {
        string name;
        public MainViewModel()
        {
            DisplayName = "My Hello App";
        }

        public string Name
        {
            get { return name; }
            set
            {
                name = value;
                NotifyOfPropertyChange(() => Name);
                NotifyOfPropertyChange(() => CanSayHello);
            }
        }
         public bool CanSayHello
        {
            get { return !string.IsNullOrWhiteSpace(Name); }
        }
         public void SayHello()
        {
            MessageBox.Show(string.Format("Hello {0}!", Name));
        }
         public string DisplayName { get; set; }
    }
}

Run the App and you should see:
CM2-Pt1-Image5
So you now have your App with a title.

Note: The IHaveDisplayName interface is also implemented in CMs IScreen and its Screen class implements IScreen. These are described later and on CM site here: https://caliburnmicro.codeplex.com/wikipage?title=Screens%2c%20Conductors%20and%20Composition

It’s a Bind

Let’s try another bit of binding between the View and ViewModel. This time it’ll be a specific item, that isn’t being automatically bound by CM.

Let us add the ability to set the colour of the TextBox from the ViewModel.

First we need to add the backing property and supporting code into MainViewModel:

private Brush _textBackgroundBrush; public Brush TextBackgroundBrush
{
    get { return _textBackgroundBrush; }
    set
    {
        _textBackgroundBrush = value;
        NotifyOfPropertyChange(() => TextBackgroundBrush);
    }
}

This creates a Brush property for the TextBox Background.

Note: This code structure is an excellent candidate for a ReSharper Live Template!

Now add calls in MainViewModel.cs to set the colour in the constructor:

public MainViewModel()
{
    DisplayName = "My Hello App";
    TextBackgroundBrush = new SolidColorBrush(Colors.BlanchedAlmond)
}

and the button click:

public void SayHello()
{
    TextBackgroundBrush = new SolidColorBrush(Colors.Chartreuse);
    MessageBox.Show(string.Format("Hello {0}!", Name));
}

Now we just need the binding in MainView.xaml:

<StackPanel>
    <TextBox x:Name="Name" 
             Background="{Binding TextBackgroundBrush, FallbackValue=LightBlue}">
    </TextBox>
    <Button x:Name="SayHello" Content="Click Me"></Button>
</StackPanel>

The FallbackValue displays in the absence of the Binding, as Binding is only made at Runtime the design colour of the TextBox will be LightBlue.

Run the application and see the colourful effect!

The complete solution is available as a zip download here (developed in Visual Studio 2013)

Catastrophic Failure in Visual Studio 2103 ( SetSite failed for package [DesignerPackage] )

I’ve been away for a couple of days, switched on my development computer, answered a few emails and then started Visual Studio 2013 to do some urgent work for a client.

I was faced by a barrage of message boxes stating that various tools and libraries could not be loaded and mentioning something about a recent update (recent update – as far as I was aware I hadn’t made any recent updates).

The project I was working on appeared to load (Unit Test runner was displayed) but nothing in any of the other panels or windows, and VisualHG seemed to recognise the project. Close and re-open a couple of times and exactly the same messages.

Tried to run the Test Runner and got the message:

ReSharper Failed to build required projects

The build could not be started. Catastropic failure (Exception from HRESULT: 0X8000FFFF (E_UNEXPECTED))

So I decide to re-boot to see if that clears things. It’s then that I see the Update icon on the Shutdown button. So, for some reason Windows has partially updated itself without telling me and screwed up VS2013! Nice one MicroSoft!

Checked ActivityLog.xml and it had loads of RED Errors – mostly MicroSoft items.

After the re-boot VS2013 was still totalled, and a quick bit of browsing found this:

http://www.jasonlinham.co.uk/2012/01/setsite-failed-for-package-visual.html

The ResetSettings parameter process did not work.

As I write this I’m running Repair on VS2013 (watching paint dry)…. Cancelled it because it was taking so long at the Preparation stage.

Later: It took about 30 minutes to complete the cancellation process but reported 93 of 96 items updated at the end and requested a reboot of the PC. After doing this VS2013 opened as though it had been just updated BUT it opened and displayed the projects and seemed to be working ok.

Luckily I had not attempted to run VS2012 before the reboot. When I did – it worked and loaded the project ok.

Lessons:

1) Be aware of when Windows has started one of it’s updates – if it’s halfway through it’ll screw up your Visual Studio if you try to run it.

2) If one version of Visual Studio is messed up – DO NOT TRY TO test another version of Visual Studio before the update has been completed !