Skip to content

Instantly share code, notes, and snippets.

@beeender
Last active August 23, 2018 17:58
Show Gist options
  • Save beeender/b2842f38b3799ca5b52e7c9ff379d7d4 to your computer and use it in GitHub Desktop.
Save beeender/b2842f38b3799ca5b52e7c9ff379d7d4 to your computer and use it in GitHub Desktop.

CaliburnMicro to make MVVM with WPF easier

Compared with MVC, MVVM does a better job to decouple the Views from other modules. It is supposed to even allow designers to write the View part. But, without the right tools, the View layer can be unbelievably complex. Don't mention the View is usually presented in XML -- the most flexible and complicated thing in the world. If you have experienced writing an application with the raw WPF, you will know what I am saying. The XAML view is getting fatter and fatter, lots of boilerplate code. Sometimes you have to write all of the boilerplate code without code completion since the data binding is dynamic. CaliburnMicro is all about writing less code in a natural way.

Nature way for data binding

Let's start with a simple example:

<Button x:Name="SayHi" Content="Say Hi" />
public bool CanSayHi { get; set;}
public void SayHi ()
{
    Say("Hi");
}

By only setting the x:Name in the View, CaliburnMicro will automatically create the connections between the x:Name and functions/properties in the ViewModel. So the button will be disabled when CanSyaHi is false, and the SayHi will be called when the button is clicked.

Do you remember how many levels of XML code and boilerplate ViewModel code you need to bind an event on a command especially you want to pass some argument to the command? Now it is quite easy:

<TextBox x:Name="Name" />
<Button x:Name="SayHi" Content="Say Hi To" />
public bool CanSayHi (string Name)
{
    return !string.IsNullOrEmpty(Name);
}
public void SayHi (string Name)
{
    Say($"Hi, {Name}");
}

This works like pure magic since CaliburnMicro does all the boring work for you. It automatically builds up the connection between the function parameter Name and the TextBox which has the same x:Name. So everything feels natural for both developers and designers. Without having the knowledge of WPF, people can easily tell those view controls are connected with which functions in the ViewModel.

The magic code is evil in the software world if the magic is too complex and unnatural. But this actually can be learned by reading a very short document here.

More reusable and more flexible Views

Consider we need a sound setting tab in the system settings window, and when the user clicks a speaker icon, we also need to pop up a window with only sound setting inside. With the raw WPF, this means lots of XAML code and lots of simple but unnecessarily stupid code. Be honest, I don't even know how to write this with pure WPF anymore since it is really boring. CaliburnMicro solves this very well:

<!-- SoundSettingView.xaml -->
<UserControl>
    ...
    <Slider x:name="Volume"/>
   ...
</UserControl>
<!-- SystemSettingsView.xaml -->
...
<TabControl x:Name="Items" />
...
public class SoundSettingViewModel : Screen
{
    //...
}
public class SystemSettingsViewModel :  Conductor<IMainScreenTabItem>.Collection.OneActive
{
    public SystemSettingsViewModel()
   {
        // Add the SoundSetting to the TabControl.
        Items.Add(new SoundSettingViewModel());
   }
}
public void ShowSoundSetting()
{
    // This will show a standalone window with sound setting only.
    IoC.GetInstance(typeof(IWindowManager), null).ShowWindow(new SoundSettingViewModel());
}

With CaliburnMicro, the Views can be separated well into different XAMLs. We control what type of the settings can be shown in code by creating and adding the specific ViewModel to the Items. Items is a property of Conductor.Collection.OneActive which our SystemSettingsViewModel derive from. CaliburnMicro takes care to connect Items and TabControl, so the SystemSettingView can create tabs for ViewModels in SystemSettingViewModel's Items and show one of them as the active tab at a time. Also, our SoundSettingViewModel can be shown as an independent window by creating and passing an instance of it to IWindowManager.ShowWindow().

More details can be seen at Screens, Conductors and Composition

Before coding with CaliburnMicro

  • Have a quick reading of All About Conventions helps you to have a general idea about what are you looking for when you get stuck.
  • The life cycle control of ViewModel is quite a useful feature of CaliburnMicro. You could easily find it when you need it.

Never torture yourself by doing MVVM with raw WPF! Get a framework like CaliburnMicro to do the boring work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment