Category Archives: Caliburn.Micro

Managing WP7 UI state with Caliburn.Micro’s guard conditions

My first Windows Phone 7 app had a lot of extraneous code whose sole purpose was enabling and disabling pieces of the user interface. Managing the visual state of buttons was one pain point. I ended up with a lot of code that looked like this:

private void ToggleButtons()
{
    if (timer.Status == "running")
    {
        StartButton.IsEnabled = false;
        EndButton.IsEnabled = true;
    }

    else if (timer.Status == "stopped")
    {
        StartButton.IsEnabled = true;
        EndButton.IsEnabled = false;
    }
}

There are about 20 things wrong with that example, but the one I’d like to focus on is how poorly conditional checks like this scale. It’s manageable when I have two buttons, but what if I had 10? Add in a third status code and the code balloons to dozens or even hundreds of lines in a hurry. (While this article focuses on MVVM, if you want to reimplement that example more elegantly in a traditional codebehind style, leave a comment. I’d be interested to see what you come up with.)

The Caliburn.Micro MVVM framework provides an elegant means for handling this scenario. Rather than setting a button’s enabled state manually, Caliburn.Micro allows you to create a boolean property that indicates whether a button can perform its intended function. If the button’s operation can’t successfully execute, the button itself is automatically disabled. Let’s look at a simple example.

Overview of the sample

The sample app illustrates how to implement a common scenario:

  • MainPage.xaml includes a textbox, a textblock and a button.
  • As long as the textbox is empty, the publish button is disabled.
  • When the user enters text in the textbox, the publish button is automatically enabled.
  • Clicking the publish button displays the entered text in the textblock

Dead-simple databinding

Here’s the entire view, minus some boilerplate and formatting attributes:

<Grid x:Name="LayoutRoot">
    <Grid x:Name="ContentGrid">
        <StackPanel >
            <TextBlock Name="PublishedText"/>
            <TextBox Name="TextToPublish" />
            <Button Content="Publish"
                    Name="Publish" />
        </StackPanel>
    </Grid>
</Grid>

I’m using Caliburn.Micro’s convention-based databinding to link the three elements in my UI to properties in the page’s viewmodel. In this case, it’s simply a matter of applying a Name attribute to each element that corresponds to a property or method name in the viewmodel. Caliburn.Micro wires them up automatically.

Properties, action messages and guards

The heavy lifting, such as it is, happens in the viewmodel:

public class MainPageViewModel : PropertyChangedBase
{
    private  string textToPublish;
    public string TextToPublish
    {
        get
        {
            return textToPublish;
        }
        set
        {
            textToPublish = value;
            NotifyOfPropertyChange(() => CanPublish);
        }
    }

    public bool CanPublish 
    { 
        get
        {
            if (string.IsNullOrEmpty(TextToPublish))
                return false;
            else
                return true;
        }
        
    }
    
    public string PublishedText { get; set; }

    public void Publish()
    {
        PublishedText = TextToPublish;
        NotifyOfPropertyChange(() => PublishedText);
    }
}

There are several key elements to this viewmodel. First, note that MainPageViewModel inherits from PropertyChangedBase, which is Caliburn.Micro’s base class implementation of INotifyPropertyChanged. The NotifyOfPropertyChange method is defined in PropertyChangedBase. Which brings me to the second important element…

The NofityOfPropertyChange calls are what tell the view that something has changed and trigger it to update itself. In this case, the TextToPublish property is updated automatically when the user enters text into the databound TextToPublish textbox. The property’s setter then pokes the view and tells it to reevaluate CanPublish.

CanPublish is what is known as a CanExecute guard condition. A guard condition is a boolean property that is paired via a naming condition to a method in the viewmodel. If the guard returns false, it blocks the method from executing, and the corresponding UI element is disabled until the CanExecute condition evaluates to true.

To implement a guard, create a boolean property and append the word Can to the beginning of the method name that the guard is associated with. In the example, CanPublish is guarding the Publish method, which is linked to the Publish button in the view.

TextToPublish kicks the view to check CanPublish, which evaluates whether any text exists in TextToPublish. If the property contains text, CanPublish returns true, and the publish button lights up to let the user know that the button is enabled.

Download the sample

A complete Visual Studio project that implements the example above is available at my Codeplex site. It was built with the February 2011 version of the Window Phone Developer tools. Other than the WP7 tools, there are no external dependencies. The Caliburn.Micro framework code is included in the Framework folder.

Leave a comment

Filed under Caliburn.Micro, MVVM, Windows Phone 7

Introduction to messaging with Caliburn.Micro’s EventAggregator

It started innocently enough. I wanted to make the phone vibrate when a countdown timer in my app reached 00:00:00. Hmmmm… What to do… I know, I’ll add an event to the Timer object and fire it at the appropriate time. Then I can create an event handler in my viewmodel and trigger the vibration.

But when I decided to add two more events to the CountdownTimer class, things started to spin out of control. Suddenly I found myself pounding out helper methods and attaching and detatching event handlers in my viewmodel and checking conditions to see which ones should be attached when… Finally my app got to the point where it was just permanently stuck at a breakpoint as some attached event somewhere fired repeatedly, ignoring my efforts to detatch it. Not cool.

That’s when I remembered Caliburn.Micro‘s support for messaging.

What is messaging?

A message is an object that is broadcast throughout your application when something important happens. When using messaging, an object “publishes” a message, which can be just about anything you want it to be. This object bubbles through your application, moving up the object hierarchy. Other objects that are subscribed to the message will receive it and can take action upon receiving it.

One of the major advantages to messaging is the way it can help you decouple classes. Because the message bubbles through the system, your subscribing code doesn’t need to know about the sender—it just listens for the message.

Traditional event handling, on the other hand, tightly couples classes together. In my timer app I was creating references to a specific instance of a concrete class, then assigning a method to be called when an event on that specific object fired:

CountdownTimer myTimer = new CountdownTimer();
myTimer.TimeExpired += OnTimeExpired;

protected void OnTimeExpired(object sender, EventArgs e)
{
    // Complete actions here.
}

Messaging, Caliburn.Micro style

Caliburn.Micro supports messaging through the EventAggregator class. The EventAggregator is a central hub, or bus, for all messages.

Using the EventAggregator is a two-step process. First, you subscribe to the aggregator in your viewmodel and create methods to handle the messages that class will receive. Second, your model classes publish messages to the aggregator when they have something to communicate.

A simple example

Let’s look at a basic app that employs messaging. Here’s what the app will do:

  • On launch, a page displays with a “Pet the Cat” button and an empty textblock that the cat will use to tell us how it’s feeling.
  • The viewmodel subscribes to messages so it can receive the cat’s response.
  • The “Pet the Cat” button triggers an action in the page’s viewmodel, which in turn calls a method on the cat object.
  • The cat object sends a message.
  • The viewmodel receives the message and it updates a property with the cat’s response. Since this property is databound to the view, the view displays the message automatically.

The full source code is available as a Visual Studio project at the end of the post. Also, I’ve simplified the code at some points in this post for clarity’s sake.

Configuring the bootstrapper

Before I can dive into the application’s logic, I need to do some setup in the AppBootstrapper class:

public class AppBootstrapper : PhoneBootstrapper
{
    PhoneContainer container;

    protected override void Configure()
    {
        ...

        container = new PhoneContainer(this);

        container.RegisterSingleton(typeof(EventAggregator), null, typeof(EventAggregator));
        container.RegisterPerRequest(typeof(MainPageViewModel), "MainPageViewModel", typeof(MainPageViewModel));
        container.RegisterPerRequest(typeof(Cat), null, typeof(Cat));

        ...
    }
}

I registered the EventAggregator class as a singleton, which means that Caliburn.Micro will only create a new instance of the class when it is first requested. Subsequent requests for an EventAggregator object will be supplied with the same instance. This ensures that the EventAggregator that the Cat class notifies will be the same one that MainPageViewModel is subscribed to. I also registering the MainPageViewModel and Cat classes to allow Caliburn.Micro to interact with them.

A simple view

The view is about as straightforward as it gets:

<Grid x:Name="ContentGrid">
    <StackPanel>
        <StackPanel>
            <TextBlock Text="The Cat Says: " />
            <TextBlock Name="CatSound" />
        </StackPanel>
        <Button Name="PetTheCat" />
    </StackPanel>
</Grid>

This example illustrates how Caliburn.Micro’s conventional binding system works. Elements such as buttons and text fields are databound automatically by the framework if their names match. It’s simple, and you get it for free with Caliburn.Micro.

Sending the message

The Cat class is responsible for sending the message that will update the UI:

public class Cat
{
    private EventAggregator eventAggregator;

    public string Sound { get; set; }

    public Cat(EventAggregator eventAggregator)
    {
        this.eventAggregator = eventAggregator;
    }

    public void MakeSound()
    {
        Sound = "Meeeeeeooooowww!";
        eventAggregator.Publish<Cat>(this);
    }
}

Notice that the object’s constructor has a parameter of type EventAggregator. This parameter is supplied automatically by Caliburn.Micro when the Cat object is first created. Enabling this dependency injection is the reason why I registered the EventAggregator and Cat classes in the bootstrapper earlier. When the MakeSound() method executes, the Cat object publishes a message of type Cat to the EventAggregator, and the Cat object supplies itself as the message object to be sent.

Tying it all together

The MainPageViewModel class pulls the pieces together.

public class MainPageViewModel : PropertyChangedBase, IHandle<Cat>
{
    private Cat cat;
    public string CatSound { get; set; }

    public MainPageViewModel(EventAggregator eventAggregator, Cat cat)
    {
        eventAggregator.Subscribe(this);
        this.cat = cat;
    }

    public void PetTheCat()
    {
        cat.MakeSound();
    }

    public void Handle(Cat cat)
    {
        CatSound = cat.Sound;
        NotifyOfPropertyChange(() => CatSound);
    }
}

There are several things to highlight here. First, note that I am subscribing to the EventAggregator in the viewmodel’s constructor. This allows the viewmodel to receive messages from other objects.

Second, the class implements the IHandle interface for the type Cat. This interface dictates that I include a method named Handle() that accepts a parameter of whatever type of message I want the viewmdoel to receive. When a message of type Cat is published, the Handle(Cat cat) method executes, assigning the value of cat.Sound to the CatSound property of MainPageViewModel.

Finally, I’m calling NotifyOfPropertyChange() after updating the CatSound property. This tells the view that a databound property was updated so the view can update itself accordingly.

Download the sample code

A complete Visual Studio project that implements the example above is available here. It was built with the February 2011 version of the Window Phone Developer tools. Other than the WP7 tools, there are no external dependencies. The Caliburn.Micro framework code is included in the Framework folder.

Leave a comment

Filed under Caliburn.Micro, MVVM, Windows Phone 7

Click handler, begone: Databinding a selected list item with Caliburn.Micro

As I’m shifting my mindset from the familiar codebehind style of development into MVVM mode, one area that often trips me up is user interactions that I used to handle with a Click event. I encountered this recently when I added a ListBox to my app. I wanted the app to update some on-screen data elements when the user touched a different item in the list.

In codebehind development, it’s obvious how to handle this: Just define a Click event handler in the list item’s XAML template, then write the logic to change the displayed data based on the selected item.

But how does this work in MVVM, where you don’t use Click events?

More databinding

Databinding is taking over a lot of the tasks I used to perform in my C#, and this is another example. Instead of using a Click handler, the example below binds the ListBox.SelectedItem property directly to a property in the viewmodel–no code required, other than the code that defines the bound properties themselves. Let’s dive in.

Simple viewmodel

There’s nothing particularly special going on in the MainPageViewModel. The List property is a container for the items that will be displayed in the ListBox. (The snippet below omits some code that populates the list with sample items when the constructor is called.) The main thing to note here is the fully implemented SelectedItem property. I used the expanded syntax because I needed to be able to call NotifyOfPropertyChange() when the item selection changes. (If anyone knows of a shorthand way to do this with auto implemented properties, please let me know in the comments.) The NotifyOfPropertyChange() call is what will trigger the UI to update itself. In this case, a TextBlock will update with the title of the selected album.

public class Album
{
    public string Title { get; set; }
    public string Artist { get; set; }
}

public class MainPageViewModel : PropertyChangedBase
    {
        private Album selectedItem;

        public Album SelectedItem
        {
            get
            {
                return selectedItem;
            }
            set
            {
                selectedItem = value;
                NotifyOfPropertyChange(() => SelectedItem);
            }
        }

        public List<Album> MyAlbumList { get; set; }
        
        ...
    }
}

Most of the work happens in the XAML listed below. I’ve stripped out the formatting and boiler plate stuff for clarity. Scan through the whole thing, then we’ll take a look at a few key snippets.

<ListBox ItemsSource="{Binding MyAlbumList}"
         SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding Title}"/>
                <TextBlock Text="{Binding Artist}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
<StackPanel>
    <TextBlock Text="Selected Album Title:" />
    <TextBlock Name="SelectedItem_Title" />
</StackPanel>

Notice that I’m binding the ItemsSource manually to the MyAlbumList property. There may be a way to accomplish the same result using Caliburn.Micro’s convention-style bindings, but this is how I was able to get it working.

The real magic is in the next attribute, SelectedItem="{Binding SelectedItem, Mode=TwoWay}". When the ListBox selected item changes, Caliburn.Micro assigns the value of the item to the SelectedItem property in the viewmodel. In this example, the viewmodel’s SelectedItem property is of type Album, which is the same type as the items in MyAlbumList.

The Mode=TwoWay setting allows the view to communicate back to the viewmodel. (Omitting this is a common databinding mistake—one I made just the other day. If actions in your UI aren’t triggering the expected response in your viewmodel, double check to make sure twoway binding is set.)

The remaining XAML is standard ListBox for binding to a list. I’m creating a template that will be used for each item and binding the list item’s properties to TextBlocks to display their contents. The Name="SelectedItem_Title" syntax may be unfamiliar; I am using a deep path property binding to get at the title of the selected list item. You could accomplish the same thing by defining a viewmodel wrapper property that returns SelectedItem.Title.

Download the sample code

A complete Visual Studio project that implements the example above is available here. It was built with the February 2011 version of the Window Phone Developer tools. Other than the WP7 tools, there are no external dependencies. The Caliburn.Micro framework code is included in the Framework folder.

5 Comments

Filed under Caliburn.Micro, MVVM, Windows Phone 7