Monthly Archives: March 2011

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.

Advertisements

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

Deep property databinding with Caliburn.Micro

My favorite thing about the Caliburn.Micro MVVM framework is how much plumbing code it is eliminating in my current Windows Phone app. The framework excels at abstracting away the goo required to get stuff to show up on the screen, letting me concentrate on my application’s logic.

One exciting Caliburn.Micro feature is its support for databinding to deep property paths. This translates to fewer “wrapper” properties in my viewmodel—properties whose sole purpose is to expose data contained in other objects.

The old way

Suppose I have a model object, CurrentUser, and I want to display the user’s FirstName property on the page. Before I learned about deep property path binding, I might have written something like this in my viewmodel:

public class MyViewModel
{
    private User currentUser;
    public string UserFirstName { get; set; }

    public void MyViewModel()
    {
        UserFirstName = currentUser.FirstName;
    }
    ...
}

And my XAML might have looked like this:

<TextBlock Name="FirstName" Text="{Binding UserFirstName}" />

Not a horrible ordeal to code, but if you have several page elements that you want to bind this way, the wrapper properties start to pile up, two lines at a time (or more, if you don’t use auto-implemented properties). This code isn’t helping me make my application better—it’s just shuffling existing data from point A to point B.

Deep property binding to the rescue

Deep property databinding allows you to skip the step of creating a wrapper property and bind straight to the nested model object using Model_Property syntax. Here’s how the example above looks when reworked using deep property databinding:

public class MyViewModel
{
    public User CurrentUser { get; private set; }
}

We’re just exposing the user object itself as a property. The magic happens in the XAML:

<TextBlock Name="CurrentUser_FirstName" />

Using conventions, the Caliburn.Micro framework will find the CurrentUser property, then drill down to the CurrentUser.FirstName property and perform the databinding.

So that’s it, and now you can get back to writing the code that allows CurrentUser to do something with your app.

Deep property databinding is covered in the Caliburn.Micro binding conventions documentation.

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.

7 Comments

Filed under MVVM, Windows Phone 7

Databinding WP7 lists to singletons with Caliburn.Micro

Databinding still seems a lot like black magic to me: You wave your hands over the keyboard, copy and paste some code from Stack Overflow, utter some dark words, and … it either works or it doesn’t. If it works, you shrug and move on. When it doesn’t … more hand-waving and increasingly dark utterances ensue.

The Caliburn.Micro framework removes a lot of the ceremony behind databinding. In most scenarios you can just name a view element, like a textbox, something like FirstName, and then make sure you have a property named FirstName in your viewmodel. Magic! Instant two-way databinding.

My current Windows Phone 7 project involves a list of data elements that will be displayed on multiple pages in the application. Rather than storing the list in isolated storage and reading it out each time one of the pages needs to display it, I’m making this list a singleton object, which will be created when the app first launches and will survive until the app closes.

The list is injected into each viewmodel that relies on it via the viewmodel’s constructor. Caliburn.Micro includes a simple IoC container that makes the injection process straightforward. Once the list has been injected into the viewmodel, I am storing the list items in a viewmodel property for display in the view.

Caliburn.Micro’s documentation is excellent, but I wasn’t able to find any example code or sample projects that showed how to databind to an injected list. I ended up thrashing around for a few hours before I found the following solution. (A complete sample project will be provided at the end of the post.) We’ll be creating an app that creates a list of cars, stores the list in a singleton object, and displays it on the page.

Let’s start by …

Creating the singleton in the bootstrapper

Any object to which you want to databind in a Caliburn.Micro project needs to be registered in the AppBootstrapper.cs file with the container.RegisterSingleton() method. Note that the second parameter, the key, should be null unless you plan to use the key to access the object later. This had me spinning my wheels for a while until Caliburn.Micro creator Rob Eisenberg pointed out my mistake. Here’s what our bootstrapper looks like:

public class AppBootstrapper : PhoneBootstrapper
{
    PhoneContainer container;

    protected override void Configure()
    {
        LogManager.GetLog = type => new DebugLogger(type);

        container = new PhoneContainer(this);

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

        ...
       
        AddCustomConventions();
    }
   
    ...
}

Building the model objects

Our model is very straightforward. The Car class contains a few simple properties. The Cars class contains a property that holds a list of Car objects. It also includes a constructor that creates several sample cars for us to work with.

public class Car
    {
        public string Make { get; set; }
        public string Model { get; set; }
        public string Year { get; set; }
    }

public class Cars
    {
        public List Items;

        public Cars()
        {
            Items = new List();
            Items.Add(new Car() { Make = "Toyota", Model = "Camry", Year = "2007" });
            Items.Add(new Car() { Make = "Ford", Model = "Fiat", Year = "1999" });
  Items.Add(new Car() { Make = "Pontiac", Model = "Firebird", Year = "1980" });
            Items.Add(new Car() { Make = "Ford", Model = "Mustang", Year = "1964" });
        }
    }


Injecting the list into the viewmodel

The Caliburn.Micro will handle injecting the list into your viewmodel almost automatically. All you need to do is include the list as a parameter in your viewmodel’s constructor. Inside the constructor, assign the injected object to a property or private variable in the viewmodel so that you can use it later:

public class MainPageViewModel
    {
  private readonly INavigationService navigationService;

  public List CarsList { get; set; }

  public MainPageViewModel(INavigationService navigation, Cars cars)
        {
  navigationService = navigation;
  CarsList = cars.Items;
        }
    }

Note that I am assigning cars.Items to the CarsList property, not just the value of cars. This was another area where I got stuck for a while. I was initially databinding directly to the Cars object, but I later realized that the Cars object contains a list; it is not in and of itself a list.

Binding the list to the view

The final step is to configure the view to display the data from the list. I’m using a ListBox with a ListBox.ItemTemplate. Caliburn.Micro handles the heavy lifting here again. I gave the ListBox an x:Name that matches the property name of the list that you’re binding to—CarsList in this case. This binds the ListBox to the list, but I still need to indicate how the properties of each list item should be displayed.
I created several TextBox elements in the DataTemplate and bound the Text properties to the various properties of the Car object:

<ListBox x:Name="CarsList">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Make}" />
                <TextBlock Text="{Binding Model}"
                           Margin="15, 0, 0, 0"/>
                <TextBlock Text="{Binding Year}"
                           Margin="15, 0, 0, 0" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Troubleshooting databinding

Currently, the Windows Phone 7 tools don’t provide much in the way of debugging for databinding. Silverlight 5 will include a debug mode, and I’m hoping this will make it into Windows Phone sooner rather than later. In the meantime, here are a few tips that have helped me at various times:

  • Make a quick demo project. This is probably my number one troubleshooting tip of all time. Create a new project and use it to implement the one feature you’re working on. You won’t be worried about messing up your real app code, and you also are able to more easily focus on solving the problem at hand.
  • Confirm that your objects are being populated appropriately. Step through your viewmodel code in debug mode and make sure that properties actually contain the values you think they do. Sometimes the problem isn’t the binding.
  • Use logging. Caliburn.Micro has a nice logging feature, which I’ve enabled in this sample project. It writes to the Visual Studio output console as it attempts to databind each element in your XAML page. You’ll see messages like No convention applied to ApplicationTitle. and Added convention binding for CarsList. that can help you figure out whether the framework is finding the properties you intend to bind to. Rob has an excellent write-up on how to enable logging on his blog.
  • Finally, make sure that you’re binding to the object at the correct level. If you have a list contained in an object, you need to expose the list itself somehow before you can bind to it.

Download the sample code

The sample project is posted in my SkyDrive. 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.

1 Comment

Filed under MVVM, Windows Phone 7

Two IE9 tricks

I’ve been using Internet Explorer 9 since it was in early beta, after I realized that FireFox 3.6 and 4 took an eternity to launch. IE9 is awesome–it’s fast, very stable, and it just stays out of the way when I’m browsing. Here are two of my favorite tips. (Disclaimer: These may have been available in previous versions of IE, but I never found them.)

Widen the URL bar

The default URL bar is distressingly small. When you get a website with a long domain name that uses SSL, all you can see is a few characters. There’s an easy fix. If you hover over the left edge of the leftmost tab, the cursor turns into a double “resize me” arrow. I widen the URL bar to occupy a little more than half of the screen width, which lets me use five or six tabs comfortably.

Change the default download location

I hate digging around the Documents folder after I download something, so I used to click Save As and browse to my desktop to make the file easier to find later. No need for that anymore. Click the gear icon next to the tab well, or press Ctrl + J. This brings up the View Downloads dialog. Click the Options link in the lower left corner, then browse to your desired default location.

Leave a comment

Filed under Web

Fixing display glitch in WP7 test projects

The Silverlight Unit Testing Framework for Windows Phone 7 is an integral part of my workflow. One thing that has bugged me every time I use it, though, is how I always saw some clipped-off graphics on the bottom of the test harness screen. It looked like some useful information–what was it?

What are those clipped elements at the bottom of the screen?

Turns out there is a simple fix. Although it isn’t noticeable, the WP7 system tray (where the clock and signal icons go) is enabled. The tray pushes the rest of the page elements down.

To disable it, open the MainPage.xaml file in your test project and set the shell:SystemTray.IsVisible="True" flag to False:


x:Class="MyApp.Tests.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
SupportedOrientations="Portrait"
Orientation="Portrait"
shell:SystemTray.IsVisible="False">

Now when you run the tests, you’ll see a bar across the bottom of the screen that summarizes the results of your test run.

The graphic turns out to be a summary of the test run. Cool!

Leave a comment

Filed under Windows Phone 7