Windows Phone 7 - mvvm Light Messaging and Dynamic Application Bar

July 20 2010

Update 22/07/2010!

You can easily bind your application bar to your page via the View Model meaning that you can handle all of this login within your view Model. This post is still valid in that it demonstrates a means of using MVVM light messaging, but there is a better way now to have dynamic application bars.

Introduction

This post will get you started with being able to dynamically update the application bar within your Windows Phone 7 (WP7) application using the core messaging framework provided by MVVM Light.

Read our MVVM Light and Unit Testing Example to understand a little more about MVVM Light if you are not familiar with the framework.

System Requirements

I’ve checked every thing against the latest public beta release of the developer tools (as of 15/07/2010) from http://developer.windowsphone.com. Please make sure you have this installed. I’m using Visual Studio 2010, but it all should work ok with Visual Studio Express 2010 that comes with the developer tools.

Application Bar Limitations

It has to be said that the application bar in Windows Phone 7 (WP7) is a strange beast. It does not derive from Control and therefore does not support binding. Laurent Bugnion has covered these deficiencies and it essentially means we have to define an application bar within our xaml pages, and resort to hard wiring event handlers into our code behind files.

This isn’t too bad, until we get to wanting to make things dynamic based user interaction with the page the menu is sitting on. In our example below, see the second button which has default text of ‘Pass’ and an IconUri set to the pass icon.

In our app, we want to trap user interaction such that when a particular condition occurs in the view model we want the icon to change out to say ‘Play’ and have a different icon.

<phoneNavigation:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar x:Name="AppBar" IsVisible="True" IsMenuEnabled="True" Opacity="1" ForegroundColor="White" BackgroundColor="Black">
            <shell:ApplicationBar.Buttons>
                <shell:ApplicationBarIconButton x:Name="recall" Click="recall_Click" IconUri="/Resources/Images/AppBar/button-recall.png" Text="Recall">
                </shell:ApplicationBarIconButton>
                <shell:ApplicationBarIconButton x:Name="passPlay" Click="passPlay_Click" IconUri="/Resources/Images/AppBar/button-pass.png" Text="Pass">
                </shell:ApplicationBarIconButton>
                <shell:ApplicationBarIconButton x:Name="swap" IconUri="/Resources/Images/AppBar/button-swap.png" Text="Swap">
                </shell:ApplicationBarIconButton>
                <shell:ApplicationBarIconButton x:Name="chat" IconUri="/Resources/Images/AppBar/button-chat.png" Click="chat_Click" Text="Chat">
                </shell:ApplicationBarIconButton>
            </shell:ApplicationBar.Buttons>
        </shell:ApplicationBar>
    </phoneNavigation:PhoneApplicationPage.ApplicationBar>

There are a number of ways you could resolve this. You could create and hook off an event in your View Model from within your view’s code behind, or if you have an existing Dependency Property on your View Model you could hook off it’s PropertyChanged event. However, a simpler and more loosely coupled approach is to use the messaging framework within MVVM Light.

Just add this single line of code to your View Model when you want to announce something to your app. The magic string is a unique token to identify the message, and you can send anything you want. In our case we are sending a message when the hasBoardThinkingTiles property has updated within the view model.

Messenger.Default.Send<bool>(hasBoardThinkingTiles), "HasBoardThinkingTiles");

You can then register to receive this message from within the constructor of your View’s code behind with a single line of code and pass off to a method for handling. You can see here that we are dynamically setting the text and icon uri depending upon the received message from the View Model.

It’s worth nothing that you cannot appear to reference Applicaiton Bar buttons by their x:Name directly like other controls you must find the button using the ApplicationBar.Buttons[x] collection directly.

public GamePage()
{
    InitializeComponent();
    Messenger.Default.Register<bool>(this, "HasBoardThinkingTiles", HasBoardThinkingTilesChanged);
}

void HasBoardThinkingTilesChanged(bool hasBoardThinkingTiles)
{
    var passPlay = ApplicationBar.Buttons[1] as ApplicationBarIconButton;
    if (hasBoardThinkingTiles)
    {
        passPlay.Text = "Play";
        passPlay.IconUri = new Uri("/Resources/Images/AppBar/button-play.png", UriKind.Relative);
    }
    else
    {
        passPlay.Text = "Pass";
        passPlay.IconUri = new Uri("/Resources/Images/AppBar/button-pass.png", UriKind.Relative);
    }
}

Conclusion

Using a messaging approach like that provided with MVVM Light helps keep your WP7 application loosely coupled. The View can remain focussed on view specific concerns and can interact with your View Model indirectly using messaging to avoid hard wiring the two together unnecessarily.

Want to get started?

We would love to help with your next app or game, please do get in touch.