Windows Phone 7 – MVVM Light Messaging and Dynamic Application Bar

Posted by: | Technical |

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 devel oper 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.

5 Responses to Windows Phone 7 – MVVM Light Messaging and Dynamic Application Bar

  1. Alek says:

    I want to change the button text on page load on soon after. How do we know when the AppBar is loaded? I want to assign the text properties but the bar keep coming back as null. I could use the sender as a reference, but once they’ve click on it is too late.

  2. manivel says:

    hi everybody

    can we hide and show the application bar when the mouse move on there?

  3. manivel says:

    2manivel

    In the Windows Phone 7 there is no mouse :) . How do you think phone can determine if user place his finger over the application bar without clicking it?

  4. Shara Owoc says:

    Hi, Neat post. There is a problem with your site in internet explorer, would test this IE still is the market leader and a large portion of people will miss your magnificent writing due to this problem.