25 February 2011

Using attached dependency properties to toggle an Application Bar Icon from viewmodel

Application Bar Icon buttons are a look-and-feel-wise very consistent and easy to understand way for every Windows Phone 7 application to give it’s users access to the most important functions. The drawback of this thing is that it’s not a real FrameworkElement, thus you cannot bind commands and other stuff to it, but as I described earlier, this has been solved by the BindableApplicationBar.

But even the BindableApplicationBar has its issues. The IconUri attribute of a BindableApplicationBarIconButton cannot be bound to – for it is no Dependecy Property. Now you can fix that, since Nicolas Humann includes the source code of his excellent solution. But I prefer to threat someone else’s code as third party component, and solved the problem using a very powerful way of extending of Silverlight/Windows Phone 7: attached dependency properties.

The problem I wanted to solve is this: I have changed my MapMania App in such a way that it now tracks your location continually if you press the “Satellite” button. But I want the user to be able to stop tracking as well, using the same button. So what used to be a simple activation button, is now a toggle button. When the user is tracking his own phone, I want the button image to change from the image of of a satellite to an image of a satellite with a big cross through it, indicating “if you press me again, I will stop tracking”. And I wanted this, of course, to be steered from the viewmodel.

This is how I solved it, with three attached dependency properties:

using System;
using System.Windows;
using Phone7.Fx.Preview;

namespace LocalJoost.Utilities
{
  /// <summary>
  /// Supports toggle of a BindableApplicationBarIconButton's icon
  /// </summary>
  public static class AppBarIconFlipper
  {
    #region IconUri
    public static readonly DependencyProperty IconUriProperty =
     DependencyProperty.RegisterAttached("IconUri",
     typeof(Uri),
     typeof(AppBarIconFlipper),
     new PropertyMetadata(IconUriPropertyChanged));

    // Called when Property is retrieved
    public static Uri GetIconUri(DependencyObject obj)
    {
      return obj.GetValue(IconUriProperty) as Uri;
    }

    // Called when Property is set
    public static void SetIconUri(
      DependencyObject obj,
      Uri value)
    {
      obj.SetValue(IconUriProperty, value);
    }

    // Called when property is changed
    private static void IconUriPropertyChanged(
     object sender,
     DependencyPropertyChangedEventArgs args)
    {
      var attachedObject = sender as BindableApplicationBarIconButton;
      if (attachedObject == null) return;
      attachedObject.IconUri = (bool)attachedObject.GetValue(ShowAlernateIconUriProperty)
                     ? (Uri)attachedObject.GetValue(AlernateIconUriProperty)
                     : (Uri)args.NewValue;
    }
    #endregion

    #region AlernateIconUri
    public static readonly DependencyProperty AlernateIconUriProperty =
     DependencyProperty.RegisterAttached("AlernateIconUri",
     typeof(Uri),
     typeof(AppBarIconFlipper),
     new PropertyMetadata(AlernateIconUriPropertyChanged));

    // Called when Property is retrieved
    public static Uri GetAlernateIconUri(DependencyObject obj)
    {
      return obj.GetValue(AlernateIconUriProperty) as Uri;
    }

    public static void SetAlernateIconUri(
      DependencyObject obj,
      Uri value)
    {
      obj.SetValue(AlernateIconUriProperty, value);
    }

    private static void AlernateIconUriPropertyChanged(
     object sender,
     DependencyPropertyChangedEventArgs args)
    {
      var attachedObject = sender as BindableApplicationBarIconButton;
      if (attachedObject == null) return;
      attachedObject.IconUri = (bool)attachedObject.GetValue(ShowAlernateIconUriProperty)
                     ? (Uri)args.NewValue
                     : (Uri)attachedObject.GetValue(IconUriProperty);
    }
    #endregion

    #region ShowAlernateIconUri
    public static readonly DependencyProperty ShowAlernateIconUriProperty =
     DependencyProperty.RegisterAttached("ShowAlernateIconUri",
     typeof(bool),
     typeof(AppBarIconFlipper),
     new PropertyMetadata(ShowAlernateIconUriPropertyChanged));

    public static bool GetShowAlernateIconUri(DependencyObject obj)
    {
      return (bool)obj.GetValue(ShowAlernateIconUriProperty);
    }

    public static void SetShowAlernateIconUri(
      DependencyObject obj,
      bool value)
    {
      obj.SetValue(ShowAlernateIconUriProperty, value);
    }

    private static void ShowAlernateIconUriPropertyChanged(
     object sender,
     DependencyPropertyChangedEventArgs args)
    {
      var attachedObject = sender as BindableApplicationBarIconButton;
      if (attachedObject == null) return;
      var value = (bool)args.NewValue;
      attachedObject.IconUri = value
                     ? (Uri)attachedObject.GetValue(AlernateIconUriProperty)
                     : (Uri)attachedObject.GetValue(IconUriProperty);
    }
    #endregion
  }
}
The only interesting code is in the “***Changed” methods, the rest is just the necessary plumbing. Anyway, in stead of setting the IconUri of the BindableApplicationBarIconButton directly, you use the attached dependency properties like this:
<Phone7Fx:BindableApplicationBarIconButton 
 Command="{Binding ShowLocation}" Text="Track" 
 LocalJoostUtils:AppBarIconFlipper.IconUri="/icons/gps.png"
 LocalJoostUtils:AppBarIconFlipper.AlernateIconUri="/icons/gps_stop.png"
 LocalJoostUtils:AppBarIconFlipper.ShowAlernateIconUri="{Binding IsTracking, Mode=TwoWay}"/>

and depending on the value of the Viewmodel property IsTracking the icon will flip from gps.png (false) to gps_stop (true) – or back.

Once again it shows Microsoft’s XAML-based platforms are as flexible as a rubber band, and wherever are holes in binding, you can almost always plug them using attached dependency properties – the super glue of MVVM, IMHO.

20 February 2011

Marketplace monetization idea: gift items

I seem to be going off-topic a lot these days but I hope you will forgive me for that.

My wife has been eying my new HTC 7 Pro quite a lot, especially since I showed her some of her favorite XBox puzzle games on it. I see where this is going to end – sooner or later (and from the looks of it rather sooner than later) her old Nokia phone will be replaced by something that runs Windows Phone 7 as well. If only because I would like to retain control over my own phone, thank you very much ;-)

And then it started to dawn on me: it would be great to buy gifts for someone else in the Marketplace.

Suppose I am browsing the Marketplace and find a game or piece of music that I know my wife (or anyone else for what matters) would like very much. I would like to be able to buy the item as a gift, i.e. I pay with my live id, but instead of installing the item on my own device I would get the option to enter someone else’s live id, and a personal note. My wife for instance would then get an e-mail on her live account (“Hi luv look what I got you”) with a Zune link, she clicks on it, the Marketplace recognizes it’s already paid for, and she gets her beloved game. Or a romantic song, or whatever.

I have no idea if this is a possible or even a viable scenario, but the thought crossed my mind yesterday evening (when my wife was watching me play a puzzle game on my phone and all but ripped it from my hands) and I just wanted to share it.

What do you think? Sensible idea, or simply not viable (too complicated for the expected ROI).?

19 February 2011

Converter to convert a single item to a list to enable Bing Maps binding

Some things are so simple that I wonder if I am missing something. I tried to bind a single GeoPosition to Bing Maps’ MapItemsControl ItemsSource on Windows Phone 7 and it did not work. Apparently Bing Maps want a list. So I wrote the following converter:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Data;

namespace LocalJoost.Convertors
{
  public class ToListConverter : IValueConverter
  {
    public object Convert(object value, Type targetType, object parameter, 
                          CultureInfo culture)
    {
      var l = new List<object> ();
      if (value != null) l.Add(value);
      return l;
    }

    public object ConvertBack(object value, Type targetType, object parameter, 
                              CultureInfo culture)
    {
      return null;
    }
  }
}
A masterpiece of complicated coding, right :-/ ? Anyway, in stead of
<Microsoft_Phone_Controls_Maps:MapItemsControl 
  ItemsSource="{Binding GpsLocation}">
I used
<Microsoft_Phone_Controls_Maps:MapItemsControl 
  ItemsSource="{Binding GpsLocation, Converter={StaticResource ToListConverter}}">

and Lo and Behold – now I did get my single icon on the map.

I have no idea if this is a quirk of the Bing Maps control or that ItemsSource attributes in general only accept lists – but either way, this works.

Extended Windows Phone 7 page for handling rotation, focused element updates and back key press

In this article I present ‘my’ base class for Windows Phone 7 Application Pages – essentially nothing more than a collection of utilities to handle common scenarios. Most of the code I did not write myself, but I think it’s a nice aggregation that handles the following three common problems:

  1. When someone is typing in a TextBox and receives a phone call, the model bound to that TextBox does not receive an NotifyPropertyChanged and thus is not updated – and if you tombstone the ViewModel, like I do, the last keystrokes are lost when the application is activated again.
  2. When a page changes from portrait to landscape, you want that transition to be animated
  3. When the users presses the back key, the ViewModel needs to be able to interact with that

I have put this class in “LocalJoost.Controls”. First, class definition and the part that handles rotation:

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Navigation;
using LocalJoost.BaseModels;
using Microsoft.Phone.Controls;

namespace LocalJoost.Controls
{
  public class ExtendedPhonePage : PhoneApplicationPage
  {
    public ExtendedPhonePage()
    {
      Loaded += ExtendedPhonePageLoaded;
    }

    void ExtendedPhonePageLoaded(object sender, RoutedEventArgs e)
    {
      _lastOrientation = Orientation;
    }
    
    PageOrientation _lastOrientation;
    protected override void OnOrientationChanged(OrientationChangedEventArgs e)
    {
      var newOrientation = e.Orientation;
      var transitionElement = new RotateTransition();

      switch (newOrientation)
      {
        case PageOrientation.Landscape:
        case PageOrientation.LandscapeRight:
          // Come here from PortraitUp (i.e. clockwise) or LandscapeLeft?
          if (_lastOrientation == PageOrientation.PortraitUp)
            transitionElement.Mode = RotateTransitionMode.In90Counterclockwise;
          else
            transitionElement.Mode = RotateTransitionMode.In180Clockwise;
          break;
        case PageOrientation.LandscapeLeft:
          // Come here from LandscapeRight or PortraitUp?
          if (_lastOrientation == PageOrientation.LandscapeRight)
            transitionElement.Mode = RotateTransitionMode.In180Counterclockwise;
          else
            transitionElement.Mode = RotateTransitionMode.In90Clockwise;
          break;
        case PageOrientation.Portrait:
        case PageOrientation.PortraitUp:
          // Come here from LandscapeLeft or LandscapeRight?
          if (_lastOrientation == PageOrientation.LandscapeLeft)
            transitionElement.Mode = RotateTransitionMode.In90Counterclockwise;
          else
            transitionElement.Mode = RotateTransitionMode.In90Clockwise;
          break;
        default:
          break;
      }

      // Execute the transition
       var phoneApplicationPage = 
           (((PhoneApplicationFrame)Application.Current.RootVisual)).Content
              as PhoneApplicationPage;
      transition.Completed += (sender, args) => transition.Stop();
      transition.Begin();

      _lastOrientation = newOrientation;
      base.OnOrientationChanged(e);
    }
  }
}
This is basically a slightly (very slightly) modified version of what is presented by Andy Wigley, only stuck in a base class.

The second part, which I nicked from The Code Project simply overrides OnNavigatedFrom – an event that is called when an App tombstones, unlike TextBox.LostFocus – and then forces the bound element to be updated. As a bonus, it tries to reset the focused element as well.

private const string FocusedElement = "FOCUSED_ELEMENT";

protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
  if (State.ContainsKey(FocusedElement))
  {
    State.Remove(FocusedElement);
  }

  var focusedElement = FocusManager.GetFocusedElement() as Control;
  if (focusedElement == null) return;
  if (!String.IsNullOrEmpty(focusedElement.Name))
  {
    State.Add(FocusedElement, focusedElement.Name);
  }

  BindingExpression be = null;

  //TODO - Developers, add additional controls here like a 
  //date picker, combobox, etc.
  if (focusedElement is TextBox)
  {
    be = focusedElement.GetBindingExpression(TextBox.TextProperty);
  }
  if (be != null)
  {
    be.UpdateSource();
  }
  base.OnNavigatingFrom(e);
}

And the third part, which I actually created myself, handles the OnBackKeyPress scenario. Sometimes you want to cancel navigation out of the page, for instance because you have created a popup. If the user then presses the back key you want to close the popup and cancel the navigation (this is actually part of the Certification Requirements), and preferably do so my letting the view model handle that. Unfortunately the only place to intercept the OnBackKeyPress event is by overriding in a method in the Page. So I simply decided to handle this by overriding the OnBackKeyPress like this:

protected override void OnBackKeyPress( CancelEventArgs e)
{
  var dc = DataContext as IBackKeyPressHandler;
  if (dc != null) dc.OnBackKeyPress(e);
}
All ViewModels that should be able to handle dc.OnBackKeyPress should then implement the very complicated interface IBackKeyPressHandler:
using System.ComponentModel;

namespace LocalJoost.BaseModels
{
  public interface IBackKeyPressHandler
  {
    void OnBackKeyPress(CancelEventArgs e);
  }
}
and you are done - the model now gets notified of the OnBackKeyPress and can handle this – or not. Of course you can do this with Messaging and whatnot – this is easy, clean and simple to understand. With on prerequisite of course: the ViewModel should be bound directly to the Page.

In stead of “phone:PhoneApplicationPage” on the top and bottom of my application pages I now simply put “LocalJoost:ExtendedPhonePage” and I am done and get the three functions described above for free. Well, that is, you need of course to define the namespace LocalJoost as something like
“xmlns:LocalJoost="clr-namespace:LocalJoost.Controls;assembly=LocalJoost" – or leave it to ReSharper or some tool like that to do that for you. 

12 February 2011

HTC 7 Pro in da house!

After my first smartphone – my honored Windows Mobile 6.0 and later 6.1 powered Samsung i780 – I got hooked on smartphones – with a physical keyboard. Don’t get me wrong, touchscreens are great for navigation, but if you are, like me, trained in ‘blind touch typing’ and in addition are blessed with a carpenter’s son hands, typing anything more than a few occasional words becomes an excruciating experience. Unfortunately, a certain company from Cupertino made made virtual keyboards into high fashion and although their keyboards are very good I never got more than 50% correct typing at a reasonable speed. I will not talk about trying to use the virtual keyboard on a HTC Hero Android device. I still dream of it, sometimes ;-).

Anyway, fast forward February 2010, the presentation of Windows Phone 7, I saw two devices with a physical keyboard, the LG Quantum and the Dell Venue Pro, and I knew I was going to one of those. Wrong. The LG never made it to Europe – allegedly because of EU regulations about radiation. The Dell Venue Pro looks like something from a science fiction show – and apparently is, for although it appeared for pre-order at several suppliers from the UK as early as November 2010 it has yet failed to materialize. At February 2, almost a year after the initial presentation I cancelled my order for the Venue Pro at Clove UK. On February 7, I received an e-mail that the HTC 7 Pro had become available. Today it arrived. The long wait is over and I can say goodbye to the prototype LG, so graciously supplied to me by Microsoft.

The phone itself

It’s physical dimensions are 11.5 x 5.5 x 1.5 cm and it weighs about 190 grams. It’s a bit on the heavy side, but it feels reassuringly solid. The weight is not without reason for there’s quite a substantial battery in there, as well as its European USP, a slide-out keyboard. Personally I don’t care about the extra weight in that light. You can find quite a bit of pictures of the HTC 7 Pro on the internet, but a review would not have been complete without mine:

Keyboard

The keyboard sports five(!) rows of keys. The keys are nicely spaced, give very little resistance but are not wobbly at all and provide a smooth typing experience. The top row is far enough from the actual screen so your thumbs won’t bump against its edge (which I experienced typing at a Omnia QWERTY) and five rows means you can type characters as well as numbers without having to resort to shift or fn keys. There is a large space bar and an enter key, a full set of cursor keys, point and comma have their own key and other often used stuff is easily accessed with the FN key. I like the fact that even the underscore is directly accessible from the keyboard - a nice geeky touch. Notice the hardly visible dots just left of the “FN” text left of the A. These are actually extremely tiny but very bright white LEDs that will light up if you use the Shift or FN key. Pressing either of these keys for a little longer make it act as Caps Lock  and FN-lock (whatever). I think this keyboard will serve me very well. The only thing I would have done differently is make a bigger backspace key. You tend to use this quite a lot ;-)

Screen

No AMOLED here folks, but nevertheless bright, vivid and smooth. When seen from an angle of 45 degrees the black seems to become gray and blue goes a little green, but it works for me. I think I will need to have a side-by-side comparison with an Omnia 7 to give a real opinion about this. [Update: I did do the compare, and I must say: compared to the Omnia the screen is really pale, but that's AMOLED for you. But it also is quite pale compared to my wife's LG Optimus 7 screen. So apparently HTC cut a little on the costs of this specialized device by putting in a lower quality screen. I know for a fact the first batch of HTC Trophy suffered from this same feat]

Phone calls

Yeah, I still do that occasionally. My wife reported good and very crisp sound from her venerable old Nokia (pun indented) and I did get good sound likewise. I have not been able to detect any antenna gate like effects, but so far I made about two calls with this phone so you never now ;-)

The camera

WP_000005Let’s say it’s good but not great (Click to see full picture). So far I took only a few pictures with it. I am used to Canon EOS 400D DSLR picture quality so this is no match anyway. I think the picture of this Witches’ Hazel is pretty good, but the results were varying. There is a led flash, which is quite good, but I don’t think it’s a good camera to shoot the standard “drunken group hug in the pub”-pictures. But then again, you mind want to reconsider using a pretty expensive device in that kind of circumstances.

 

 

Sound

It’s a good music player, and then the Sound Enhancer come into play. When you plugin the headphone (which you do, for you don’t want to bother your fellow human being with your particular choice of music, eh ;-)? ) , the sound is quite thin –  until you start playing with Sound Enhancer. The “bass booster” setting gives quite an impressive thunder. I used it to play a Youtube video – without headphones, ahem – and my wife commented about the good sound quality.

Other hardware – and concerns about that

The back cover is solid metal and unlike a German review I read stated, it’s very easy to open. That is, provided you take the time to read the manual, in which the correct procedure is quite extensively described: first slide out the keyboard, that reveals a notch, put your fingernail there and then you easily pop open the back cover. No messing around with screwdrivers or knives. Remove battery, insert SIM card as depicted in manual, replace battery and cover, ready. Should take less than a minute.

The device sports quite a big volume rocker on the left side that is easy to operate. The power button is on top, and is a bit small for my taste, but it works. The same goes for the camera button on the left bottom – small but usable, and easier to find than the power button, The standard Windows Phone 7 Back, Start and Search button are not buttons at all but virtual buttons – you have to so much as touch them and they are activated. Which, I think, will mightily annoy game fans because sooner or later you will inadvertently hit such a button and poof goes your game. For me, it will take some getting used to, but that’s okay. There is a headphone plug and a Micro USB port – placed  on the side, the place where I like it most. I would have liked it even better on the other side, for now it is sitting on the ‘front’ side when the slider is open.

My biggest concern with this device is the slider mechanism. The slider itself feels solid enough, but once slided out the screen flips up. It looks cool, the phone looks like a miniature laptop top but that flip-up mechanism feels a tad vulnerable – I wonder how much durability tests went into that and how long it will last. Time will tell. [Update: the flip-up system makes it possible to put the device rock solid on a table and use it as a ‘dining table top’ Youtube player, or scroll through tweets or news and even typing with my left hand. Seen from that perspective the fact that the back button is a virtual button is very handy – you now only have to touch it a little and it activates. Pressing a physical button would make the device device topple backwards]. [Update 2: in 3 months the device has suffered two bad drops with the slider open, and although it fell apart in three parts (phone, battery pack and battery cover) it apparently suffered no ill effect. So the slider/flip-up mechanism apparently is pretty solid]

Also included in the package I got was a Bluetooth headset. Not that I needed one, but nice, still.

Software

Whether you like it or not, it runs Windows Phone 7. You may have noticed I like that fact very much indeed, as well as the fact that it runs Windows Phone 7 like it’s on steroids. The animations are very smooth after living on a prototype for over two months. There are some extra things aboard, like the HTC Hub which I haven’t even fully explored yet but which seems to include some weather gadget, a Youtube player, the already mentioned Sound Enhancer. In addition, a Photo Enhancer, a unit convertor (sorry Maurice) a Connection Setup Wizard and some other applications seem to be pre-installed. HTC also seems to have included a lot of ringtones that weren’t included on the prototype so I guess they are extra too.

Impatience has a price

As I wrote earlier this device comes from Clove UK. You can see this on the keyboard – there’s a Pound Sterling sign in stead of a Dollar sign. I don’t care about that. What I do care about is that both the phone and the headset come with a separate charger – both only support UK style wall sockets. I guess it’s the price I pay for my impatience, but then again, if you ship to the European mainland you should at least point this out to your customers. Even better is a link to ‘order your convertor plug here’ – and best is to include a convertor plug free of charge (in stead of a head set). Anyway, I went to the phone shop on the corner and forked over €18 for a standard HTC Micro USB charger. Since I now don’t have to buy an extra USB cable I am only about €10 down, but still, it feels a bit inconsiderate. Anyone from the UK interested in two Micro USB chargers? You can get them from me ;-)

Overall feeling

After a fellow #wp7nl developer’s disastrous experiences with the HTC Tytn II I grew a bit weary of HTC. So why did I buy this device? Three reasons:

  1. Windows Phone 7
  2. Physical keyboard
  3. Available in or shippable to the Netherlands

So I bought HTC, because there was simply no competition. I hope phone manufacturers will take note of this. I am not alone in preference 2 – just watch all the youngsters walk around with BlackBerry devices. My advice: stop aping the iPhone, and corner that part of the business before RIM gets everything.

Anyway: what I’ve seen from the HTC 7 Pro – it feels good, it runs smoothly, and now I have a Windows Phone 7 device on which I can do some serious development, with a seriously usable keyboard that I can use for making notes, posting messages and blog comments, and boring you all on Twitter till the cows come home. I’d rather not think about the fact that including the charger I shelled out about €560 to finally lay may hands at a phone that meets my specs, but for now I am very satisfied with this device and in the end, that’s what counts for me.

11 February 2011

A Blendable Windows Phone 7 / Silverlight clipping behavior

If you are moving images around on a Canvas, you don’t want to show them when they get, for example, a negative Y-coordinate – for else they move outside of the Canvas and over what is above that. I’ve seen numerous examples of clipping ‘utilities’ that basically all ape this article on The Code Project. For some reason no-one seems to have thought about making it a real behavior that can be used from Blend. So after a short discussion over Twitter and DM with Thomas Woo (aka @codechinchilla) I decide to do my own take.

It’s not exactly rocket science:

using System.Windows;
using System.Windows.Media;
using System.Windows.Interactivity;

namespace LocalJoost.Behavior
{
  public class ClipToBoundsBehavior: Behavior<FrameworkElement>
  {
    protected override void OnAttached()
    {
      base.OnAttached();
      AssociatedObject.SizeChanged += AssociatedObjectSizeChanged;
      AssociatedObject.Loaded += AssociatedObjectLoaded;
    }

    protected override void OnDetaching()
    {
      AssociatedObject.SizeChanged -= AssociatedObjectSizeChanged;
      AssociatedObject.Loaded -= AssociatedObjectLoaded;
      base.OnDetaching();
    }

    void AssociatedObjectLoaded(object sender, RoutedEventArgs e)
    {
      SetClip();
    }

    void AssociatedObjectSizeChanged(object sender, SizeChangedEventArgs e)
    {
      SetClip();
    }

    private void SetClip()
    {
      AssociatedObject.Clip = new RectangleGeometry
      {
        Rect = new Rect(0, 0, 
          AssociatedObject.ActualWidth, AssociatedObject.ActualHeight)
      };
    }
  }
}

…and it’s even less code than the original sample. Drag this thingie in Blend on your Canvas - or whatever other framework element whose children you want to display only within its bounds - and you’re done. Or your designer is done.

I made this for a little Windows Phone 7 App I am currently working on, but it will pretty much work in plain Silverlight, and I am pretty sure it will work on WPF (and thus Microsoft Surface) as well.

08 February 2011

The case for the Bindable Application Bar for Windows Phone 7

I’ve said it once and I’ll say it again:

”Thou shalt not make unto thee any Windows Phone 7 application without MVVMLight

Even when using Application Bar. I strikes me as very odd that people still use that thing for an excuse to bypass the model or even forego MVVM. As early as August a French .NET consultant called Nicolas Humann wrote an excellent blog post about an implementation of a bindable wrapper for the Application Bar. You can simply download the Phone.Fx.Preview project, add this as a project to your Windows Phone 7 solution and then, in stead of  having something like this:

<phone:PhoneApplicationPage.ApplicationBar>
  <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
    <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png"
       Text="Button 1"/>
    <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" 
       Text="Button 2"/>
    <shell:ApplicationBar.MenuItems>
      <shell:ApplicationBarMenuItem Text="MenuItem 1"/>
      <shell:ApplicationBarMenuItem Text="MenuItem 2"/>
  </shell:ApplicationBar.MenuItems>
  </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
and hooking up events to code in the code behind of the XAML, and then doing something complicated with messages or maybe event casting the DataContext of the page to your model type and then calling methods directly - in stead of all this hoopla and duct tape programming you can simply use
<Phone7Fx:BindableApplicationBar x:Name="AppBar" IsVisible="true" >
  <Phone7Fx:BindableApplicationBarIconButton Command="{Binding Command1}" 
    Text="Button 1" IconUri="/Images/appbar_button1.png" />
  <Phone7Fx:BindableApplicationBarIconButton Command="{Binding Command2}" 
    Text="Button 2" IconUri="/Images/appbar_button2.png" />
  <Phone7Fx:BindableApplicationBarMenuItem   
    Command="{Binding Command3}" Text="MenuItem 1" />
  <Phone7Fx:BindableApplicationBarMenuItem   
    Command="{Binding Command3}" Text="MenuItem 2" />  
</Phone7Fx:BindableApplicationBar>

and let the model do the work as it should.

The bindable application bar should be in the toolkit of every Windows Phone 7 developer. Case closed.