Monthly Archives: June 2014

Caliburn Micro Part 4: The Event Aggregator

Welcome to the fourth part of this tutorial on the basics of Caliburn Micro, in the previous part we saw how actions worked. In this next part we will go through the basics of the Event Aggregator.

Description

The event aggregator is a service that allows View Models to communicate with each other using messages. A View Model can subscribe to as many messages as it wants and will be notified each time one of these messages is published by the same or a different View Model.

Step 1: New Components

In this example we will build a small application that changes the text in one View Model when buttons in another are pressed, we will build upon the application that we built in the past tutorials. In order to do this we will need two additional View Models, so lets start by creating the one containing the buttons. Create a new class, call it ButtonsViewModel and add code so that it looks as below.

public class ButtonsViewModel
{
    public void Button1()
    {
    }

    public void Button2()
    {
    }

    public void Button3()
    {
    }
}

Lets also make a View to go along with it as well called ButtonsView.

<UserControl x:Class="CaliburnMicroExample.ButtonsView"
             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" >
    <StackPanel Orientation="Vertical">
        <Button x:Name="Button1" Content="Button 1" />
        <Button x:Name="Button2" Content="Button 2" />
        <Button x:Name="Button3" Content="Button 2" />
    </StackPanel>
</UserControl>

Now that we have the buttons set up lets create the View Model that will display some text to the user. Create a new View Model and call it TextViewModel.

public class TextViewModel : PropertyChangedBase
{
    private string _text;

    public string Text
    {
        get { return _text; }
        set
        {
            _text = value;
            NotifyOfPropertyChange(() => Text);
        }
    }

    public TextViewModel()
    {
        Text = "No button pressed";
    }
}

Also create TextView to go along with it.

<UserControl x:Class="CaliburnMicroExample.TextView"
             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" >
    <Grid>
        <TextBlock x:Name="Text" VerticalAlignment="Center" />
    </Grid>
</UserControl>

Finally we need to update ShellViewModel and ShellView so that they contain the new View / View Model combos we have made. Start by changing ShellViewModel as below.

public class ShellViewModel
{
    public ButtonsViewModel ButtonsVM
    {
        get;
        set;
    }

    public TextViewModel TextVM
    {
        get;
        set;
    }

    public ShellViewModel()
    {
        ButtonsVM = new ButtonsViewModel();
        TextVM = new TextViewModel();
    }
}

Change ShellView as shown below.

<UserControl x:Class="CaliburnMicroExample.ShellView"
             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"
             xmlns:local="clr-namespace:CaliburnMicroExample"
             mc:Ignorable="d" >
    <StackPanel Orientation="Horizontal">
        <local:ButtonsView cal:Bind.Model="{Binding ButtonsVM}" />
        <local:TextView cal:Bind.Model="{Binding TextVM}" />
    </StackPanel>
</UserControl>

If you run the program now you should see a small app with 3 buttons down the left hand side and some text displayed to the right.

Step 2: Implementing IHandle

We are going to be publishing messages from the ButtonsViewModel that will be picked up in the TextViewModel. To do this we need to make TextViewModel aware of the message that it is going to receive. Caliburn offers the IHandle interface which lets a View Model listen for a message of its choice, start by creating a new class and calling it ChangeTextMessage. This will act as the message that we send between our two View Models.

public class ChangeTextMessage
{
    public string Text
    {
        get;
        private set;
    }

    public ChangeTextMessage(string text)
    {
        Text = text;
    }
}

Now lets extend TextViewModel to support the IHandle interface, as you can see below once we received the message we set the text that is displayed to the text received in the message.

public class TextViewModel : PropertyChangedBase, IHandle<ChangeTextMessage>
{
    private string _text;

    public string Text
    {
        get { return _text; }
        set
        {
            _text = value;
            NotifyOfPropertyChange(() => Text);
        }
    }

    public TextViewModel()
    {
        Text = "No buttons pressed";
    }

    public void Handle(ChangeTextMessage message)
    {
        Text = message.Text;
    }
}

Step 3: Event Aggregator

Now that we have added the ability for TextViewModel to handle a message we need to start adding the capability for it to receive them and for ButtonsViewModel to send them. To do this we need to pass an instance of EventAggregator to each of our interested View Models, start by creating a new instance of it in the ShellViewModel constructor and passing it to the other two View Models.

public ShellViewModel()
{
    IEventAggregator events = new EventAggregator();

    ButtonsVM = new ButtonsViewModel(events);
    TextVM = new TextViewModel(events);
}

In TextViewModel save the passed in instance to a local variable.

private IEventAggregator _events;

public TextViewModel(IEventAggregator events)
{
    _events = events;

    Text = "No buttons pressed";
}

Do the same in ButtonsViewModel as well.

private IEventAggregator _events;

public ButtonsViewModel(IEventAggregator events)
{
    _events = events;
}

Step 4: Subscribe

The next step is to subscribe TextViewModel to the Caliburn message pipe, this is as simple as calling subscribe on the EventAggregator object that we passed in.

public TextViewModel(IEventAggregator events)
{
    _events = events;

    _events.Subscribe(this);

    Text = "No buttons pressed";
}

Step 5: Publish

The final thing we need to do is send a message every time a button is pressed in ButtonsViewModel, extend your code as shown below.

public void Button1()
{
    _events.PublishOnUIThread(new ChangeTextMessage("Button 1 Pressed"));
}

public void Button2()
{
    _events.PublishOnUIThread(new ChangeTextMessage("Button 2 Pressed"));
}

public void Button3()
{
    _events.PublishOnUIThread(new ChangeTextMessage("Button 3 Pressed"));
}

If you run the application now you should see that pressing buttons on the left changes the text on the right.

That’s it for this tutorial join us next time for a look at using Caliburn Micro in Windows Phone 8.1 and Windows Store projects.

Caliburn Micro Part 3: Actions

Welcome to the third part of this tutorial on the basics of Caliburn Micro, in the previous part we saw how to do some basic databinding and eventing. In this next part we will go through the basics of actions.

Long Syntax

Last time we saw how to bind the click event of a button to a function in the associated View Model, by setting the name of the button to the name of the function. This works well if you only want to bind to the default event but what if you wanted to bind to a different event or even pass parameters?

Lets start by changing out previous example to use the long syntax. Edit the xaml in ShellView to look as follows.

<Grid>
    <Button Content="Press Me" VerticalAlignment="Top">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
                <cal:ActionMessage MethodName="ChangeMessage" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Button>
    <TextBlock x:Name="Message" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Grid>

You’ll need to add these two namespace references as well.

xmlns:cal="http://www.caliburnproject.org"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

If you run the app now you should see that it runs exactly the same as before. All we have done here is explicitly say which event we are listening for and which function in the View Model should be called.

Next lets look at how we can pass parameters with the action message, modify ShellView as follows so that it passes a parameter when the button is clicked.

<Button Content="Press Me" VerticalAlignment="Top">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <cal:ActionMessage MethodName="ChangeMessage">
                <cal:Parameter Value="2" />
            </cal:ActionMessage>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

Next edit the ChangeMessage function in ShellViewModel so that it takes an integer parameter.

public void ChangeMessage(int incrementBy)
{
    _pressCount += incrementBy;

    Message = "Presses = " + _pressCount;
}

If you run the app again you should notice that the count is now increased by two, this is because when the button is clicked it sends the action message to the View Model with the specified parameter which is then added to the count.

Short Syntax

If the above seemed like a quite a lot of xaml it can be shorted by using the short action message syntax. We can achieve what we did before by modifying ShellView like below.

<Button Content="Press Me" VerticalAlignment="Top" cal:Message.Attach="[Event Click] = [Action ChangeMessage(2)]" />

What we have done here is use one of Caliburn Micros attached properties to achieve the same as we did before but with much less xaml. I like this method as it simplifies the code somewhat, but in more complex cases it may be clearer to use the longer syntax.

In addition to passing literal values and binding expressions as parameters it is also possible to pass some special values that allow you access to some convenient information. These are as follows:

$eventArgs
Passes the EventArgs or input parameter to your Action.
$dataContext
Passes the DataContext of the element that the ActionMessage is attached to.
$source
The actual FrameworkElement that triggered the ActionMessage to be sent.
$view
The view (usually a UserControl or Window) that is bound to the ViewModel.
$executionContext
The action’s execution context, which contains all the above information and more.
$this
The actual UI element to which the action is attached. In this case, the element itself won’t be passed as a parameter, but rather its default property.

That’s it for this tutorial join us next time for a look at the Event Aggregator.

Caliburn Micro Part 2: The Basics of Databinding

Welcome to the second part of this tutorial on the basics of Caliburn Micro, in the previous part we saw how to setup a new project from scratch and display a window to the user. In this next part we will go through the basics of databinding which is where the true power of Caliburn Micro comes into play. We will be building upon the example shown in the previous part of this tutorial by adding some new functionality to it.

Databinding

Lets start simple by showing some text to the user. Extend ShellViewModel as shown below by adding a string property and setting it to HelloWorld in the constructor. Notice that we are now inheriting from PropertyChangedBase and we’ve added a call to NotifyOfPropertyChange in the setter of the property. PropertyChangedBase gives us access to NotifyOfPropertyChange which tells the view that it should display the new value every time the Message property is changed. This saves us from having to implement the INotifyPropertyChanged interface in all of our ViewModels.

using Caliburn.Micro;

namespace CaliburnMicroExample
{
    public class ShellViewModel : PropertyChangedBase
    {
        private string _message;

        public string Message
        {
            get { return _message; }
            set
            {
                _message = value;
                NotifyOfPropertyChange(() => Message);
            }
        }

        public ShellViewModel()
        {
            Message = "Hello World";
        }
    }
}

Next lets add a TextBlock to ShellView so that it can display our message to the user.

<Grid>
    <TextBlock x:Name="Message" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Grid>

Now if you run up the application you should see a small windows with the text Hello World in the centre. By just giving the TextBlock the same name as out property Caliburn Micro automatically binds them together for us. This is not the only way to do it however, you could do it the traditional way by binding to the Text property of the TextBlock.

<Grid>
    <TextBlock Text="{Binding Message}" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Grid>

Events

Now lets look at how Caliburn Micro handles events, in order to do this we will add a button to our application that lets us change the current text. First add a new function to ShellViewModel that changes the message as shown below.

using Caliburn.Micro;

namespace CaliburnMicroExample
{
    public class ShellViewModel : PropertyChangedBase
    {
        private string _message;

        public string Message
        {
            get { return _message; }
            set
            {
                _message = value;
                NotifyOfPropertyChange(() => Message);
            }
        }

        private int _pressCount;

        public ShellViewModel()
        {
            Message = "Hello World";
            _pressCount = 0;
        }

        public void ChangeMessage()
        {
            _pressCount++;

            Message = "Presses = " + _pressCount;
        }
    }
}

Now add a button to ShellView as shown below.

<Grid>
    <Button x:Name="ChangeMessage" Content="Press Me" VerticalAlignment="Top" />
    <TextBlock x:Name="Message" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Grid>

That’s all there is to it, if you run the application now you should see that pressing the button changes the message displayed. The binding is achieved in pretty much the same way as with the TextBlock, Caliburn Micro looks for a function in the ViewModel with the same name as the Button and binds the two together so that the function is called on the button press. There are additional ways to do this which give you more control but we’ll look at those in a future tutorial.

Event Guards

The last thing we are going to cover in this tutorial is event guards. Event guards are used to only allow the handling of an event if a certain condition is met. To demonstrate this we will prevent the user from pressing the button more than 10 times. Add a new property to ShellViewModel called CanChangeMessage and also add a new NotifyOfPropertyChange to the Message setter.

public string Message
{
    get { return _message; }
    set
    {
        _message = value;
        NotifyOfPropertyChange(() => Message);
        NotifyOfPropertyChange(() => CanChangeMessage);
    }
}

public bool CanChangeMessage
{
    get { return _pressCount < 10; }
}

Now when you run the code you should see that the button becomes disabled after it has been pressed 10 times. Every time Caliburn Micro hooks up an event is also looks for a property with the same name plus the word can before it. It then uses the Boolean result of the property to determine whether the event should be handled or not. So in this case once the press count has reached 10 the property will always return false meaning no new click events will be handled and Caliburn Micro automatically disables the button for us.

In the next part of this blog series I will go through how Actions work in Caliburn Micro.

Caliburn Micro Part 1: Getting Started

In this blog series I’ll go through the steps needed to get up and running with Caliburn Micro, we’ll be using a wpf application as an example although caliburn micro also supports Silverlight, Windows Phone and Windows Store apps.

Step 1: Initial Setup

Start by creating a new wpf application in Visual Studio and grab the Caliburn Micro nugget package using the library package manager. Since Caliburn Micro takes care of creating all windows for you, delete MainWindow.xaml and remove the StartupUri attribute from App.xaml. After doing the previous App.xaml will look like this.

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

Step 2: Creating a View Model

Since Caliburn Micro prefers a View-Model-First approach lets start by creating our first View Model. Add a new class to the project and call it ShellViewModel. Since we are just getting setup in this tutorial we won’t add any functionality to the VM. After you have created ShellViewModel it should look as below.

namespace CaliburnMicroExample
{
    public class ShellViewModel
    {
    }
}

Note that the names of View Models in Caliburn Micro must end with ViewModel although what you put before that is up to you.

Step 3: Creating a View

In order to display something to a user we’ll need a View to go along with the View Model, create a new wfp user control and call it ShellView. The xaml for the view you created should look as below.

<UserControl x:Class="CaliburnMicroExample.ShellView"
             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"
             Width="100" Height="100">
    <Grid>
            
    </Grid>
</UserControl>

Note that Views in Caliburn Micro must end with View and have the same name as the View Model, so having a View Model called MyViewModel would mean that the associating View is called MyView. This is so that Caliburn Micro can automatically bind them together.

Step 4: The Bootstrapper

Finally we need a Bootstrapper which will configure the Caliburn Micro framework and tell it what to do. Bootstrappers can do quite a lot of things beyond the scope of this tutorial so for now we will just configure one that initialises the framework and displays the first View. So create a new class and call it AppBootstrapper, then add code to make it look like the one below.

using Caliburn.Micro;

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

        protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
        {
            DisplayRootViewFor<ShellViewModel>();
        }
    }
}

The last thing to do is to tell the application to use the bootstrapper on startup, to do this we need to edit App.xaml as shown below.

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

That’s all there is to it, if you run the application now you should see a small square window. You are now ready to take advantage of all the cool things that Caliburn Micro has to offer.

In the next part of this blog series I will go through how databinding and events work in Caliburn Micro.

Optional Arguments

The definition of a method, constructor, indexer or delegate can specify that a parameter is optional. Any caller must provide all required arguments but does not have to specify optional ones.

Each optional parameter has a default value as part of its definition that is used if an argument for it is not specified.

public void MyFunction(int parameterOne, string optionalPerameter = "Hello World")
{
}

In the example above the string Hello World will be passed into the function if the caller decides not to pass in an argument for that parameter.

Optional parameters are defined at the end of the argument list, after any required arguments. If the caller provides an argument for any optional parameter it must provide arguments for all previous optional parameters.

Creating Random Colours

Occasionally the need might arise to generate a partial or fully random colour, but there is no inbuilt C# function that will allow you to do this. However this is a fairly easy thing to do yourself using the System.Random class.

public class ColourCreator
{
    private Random _random;

    public ColourCreator()
    {
        _random = new Random();
    }

    private Color CreateRandomColour()
    {
        return Color.FromRgb((byte)_random.Next(255), (byte)_random.Next(255), 
            (byte)_random.Next(255));
    }
}

As you can see from the code above it is just a simple case of creating a colour from RGB values which are randomised between 0 and 255 in this example. This example could be extended to include Alpha as well by using Color.FromArgb.

private Color CreateRandomColour()
{
    return Color.FromArgb((byte)_random.Next(255), (byte)_random.Next(255), 
        (byte)_random.Next(255), (byte)_random.Next(255));
}

Note that you need to include a reference to PresentationCore to get access to the Color class.

NSubstitute – Capturing Arguments Passed To A Function

Consider the situation where you are writing a unit test and need to find out what the value of an argument was that was passed to a function. This can be achieved using NSubstitute.

public interface MyInterface
{
    void MyFunction(int parameterOne);
}

public class MyClass : MyInterface
{
    public void MyFunction(int parameterOne)
    {
    }
}

public class Foo
{
    private MyInterface _myClass;

    public Foo(MyInterface myClass)
    {
        _myClass = myClass;
    }

    public void DoWork()
    {
        _myClass.MyFunction(20);
    }
}

Looking at the code above, we are passing the value 20 into MyFunction but we want to unit test that 20 is the value that actually gets passed in. So how do we do that?

[Test]
public void TestThat20IsPassedToMyFunction()
{
    MyInterface myClass = Substitute.For<MyInterface>();

    Foo foo = new Foo(myClass);

    int result = 0;

    myClass.MyFunction(Arg.Do<int>(arg => result = arg));

    foo.DoWork();

    Assert.AreEqual(20, result);
}

Firstly we mock an instance of MyInterface using NSubstitute so that we can determine when functions are called on it. Then we use the Arg.Do statement to capture the passed in arguments to MyFunction and store them in the result variable. Finally its just a simple matter of calling the function we want to test and asserting that the value in result is 20.

Named Arguments

Named arguments enable you to specify an argument for a particular parameter by associating the argument with the parameters name rather than with the parameters position in the parameter list.

Normally arguments are specified in the order that they appear in the parameter list as shown below.

public class Program
{
    private static void Main(string[] args)
    {
        int argumentA = 10;
        double argumentB = 2.5;

        double result = MyFunction(argumentA, argumentB);
    }

    private static double MyFunction(int paramterA, double paramaterB)
    {
        return paramaterB + paramterA;
    }
}

Named arguments free you from the need to remember to look up the order of parameters in the parameter list of called methods. Arguments can be specified in any order by using the name of the parameter.

public class Program
{
    private static void Main(string[] args)
    {
        int argumentA = 10;
        double argumentB = 2.5;

        double result = MyFunction(paramaterB: argumentB, paramterA: argumentA);
    }

    private static double MyFunction(int paramterA, double paramaterB)
    {
        return paramaterB + paramterA;
    }
}

A named argument can follow a positional argument as shown below.

public class Program
{
    private static void Main(string[] args)
    {
        int argumentA = 10;
        double argumentB = 2.5;

        double result = MyFunction(argumentA, paramaterB: argumentB);
    }

    private static double MyFunction(int paramterA, double paramaterB)
    {
        return paramaterB + paramterA;
    }
}

But a positional argument cannot follow a named argument, attempting to do this would cause a compilation error.

Out Parameters

The out keyword causes values to be passed by reference, this is very much like the ref keyword but variables do not have to be initialised first. To use out parameters, both the method definition and calling method must explicitly use the out keyword.

public class Program
{
    private static void Main(string[] args)
    {
        int foo;

        MyFunction(out foo);
    }

    private static void MyFunction(out int foo)
    {
        foo = 10;
    }
}

A couple of things should be noted:

  • The called method must always assign a value to the out parameter before the function returns.
  • Properties cannot be passed as out parameters since they are not variables.
  • Async functions defined with the async modifier cannot accept out parameters.
  • Iterator functions which include a yield return or yield break statement can also not accept out parameters.

Declaring out parameters is most useful when you would like a function to be able to return multiple values. A function that uses out parameters can still return a value as its return type but it can also return one or more objects to a calling method as out parameters.

public class Program
{
    static void Main(string[] args)
    {
        int foo;
        double bar;

        bool result = MyFunction(24, out foo, out bar);
    }

    private static bool MyFunction(int input, out int foo, out double bar)
    {
        if (input > 10)
        {
            foo = input * 10;
            bar = input / 2.5;

            return true;
        }
        else
        {
            foo = 0;
            bar = 0;
        }

        return false;
    }
}

Nullable Types

Nullable types represent value-type variables that can be unsurprising assigned the value null. They are especially useful in instances where databases are involved due to the fact that database entries may not be assigned a value.

They can be created in two different ways either using System.Nullable or ?.

Nullable<int> foo = null;
int? bar = null;

Nullable types can be checked to see if they contain a value by checking the .HasValue field and their value can be returned by using .Value.

if (foo.HasValue)
{
    int bar = foo.Value;
}

GetValueOrDefault() can be used to return the default value of the type if the value is currently null and ?? can be used to assign a default value that will be used when a nullable type whose current value is null is assigned a non-nullable type.

int bar = foo.GetValueOrDefault();

int? x = null;
int y = x ?? -1;