The problem of the Windows Phone 7 ApplicationBar and not (yet) updated Bindings

As a MVVM enthusiast I’m trying to use MVVM as much as possible, but not for things that are almost impossible to do with MVVM. But simple things, like a TextBox Text property is always bound to a ViewModel’s property. That’s something that works very well…until you start having ApplicationBar buttons and menu items.

A lot of people already know that the ApplicationBar is something special, it’s not just a control like other stuff in your application. When clicking a button on the ApplicationBar the Binding is not yet updated. This is basically because the focus which is on the TextBox for example won’t be changed when clicking ApplicationBar buttons. This is different compared to normal buttons that you put somewhere on your page.

The Solution?

I’ve read different solutions on the web. For example, force focus on a different control by calling the Focus method on a Control. While this is working, I found a technically nicer solution. By getting the Binding of the current focused control and updating that binding.

I wrote a small helper class that implements this Binding updating.

public static class ApplicationBarHelper
{
    public static void UpdateBindingOnFocussedControl()
    {
        object focusedElement = FocusManager.GetFocusedElement();
        if (focusedElement != null && focusedElement is TextBox)
        {
            var binding = (focusedElement as TextBox).GetBindingExpression(TextBox.TextProperty);
            if (binding != null)
                binding.UpdateSource();
        }
    } 
}

The first thing you do in the Event handlers for the ApplicationBar Click events is call.

ApplicationBarHelper.UpdateBindingOnFocussedControl();

What about the BindableApplicationBar?

A lot of use MVVM enthusiasts are using the BindableApplicationBar that’s part of the Phone7.Fx library. Can we use this in combination with the BindableApplicationBar? Yes we can, actually the best way would be to have this integrated with the BindableApplicationBar itself. I have just downloaded the source and manipulated two methods in two classes.

public class BindableApplicationBarIconButton : FrameworkElement, IApplicationBarIconButton
{
    // Other code that hasn't been changed in this class.

    void ApplicationBarIconButtonClick(object sender, EventArgs e)
    {
        ApplicationBarHelper.UpdateBindingOnFocussedControl();
        if (Command != null && CommandParameter != null)
            Command.Execute(CommandParameter);
        else if (Command != null)
            Command.Execute(CommandParameterValue);
        if (Click != null)
            Click(this, e);
    }
}

public class BindableApplicationBarMenuItem : FrameworkElement, IApplicationBarMenuItem
{
    // Other code that hasn't been changed in this class.

    private void ApplicationBarMenuItemClick(object sender, EventArgs e)
    {
        ApplicationBarHelper.UpdateBindingOnFocussedControl();
        if (Command != null && CommandParameter != null)
            Command.Execute(CommandParameter);
        else if (Command != null)
            Command.Execute(CommandParameterValue);
        if (Click != null)
            Click(this, e);
    }
}

What does featuring in the Marketplace do with your app?

A lot of Windows Phone developers probably already know, but some might not. There is a very interesting tool in the market to monitor your application for Downloads, Ranking and Reviews: Distimo Monitor. You can for example compare your application with your competition and conquer the world. Besides that Distimo also shows you when your application was featured in the Marketplace. A couple of the apps I created have been featured so far, but let’s look at Fokke & Sukke app and the target market (The Netherlands).

Is my app featured?

You can watch closely how the marketplace looks either on the Phone or in Zune to see if your app is featured.

image

But in the end, this is not very doable. Don’t forget that your app can be featured in every market separately. So what else? We have the distimo monitor which shows events for your application. You can see when a new version was released and when your app was featured.

image

The featured periods are:

  • 12/10 – 18/10
  • 02/11 – 08/11
  • 30/11 – 06/12

My app is featured, now what?

It’s cool to see that this app has been featured that often, but what does it mean? Let’s take a look at the Ranking in those periods.

image

You can easily see the areas when the app was featured by the green regions. But more important, you can see that in the first and third period being featured meant that the ranking went up immediately.

How to give an element focus when something happens?

I had a very simple problem: On loading of particular screen I wanted to give a TextBox focus. It’s freaking easy to do this in the code behind. Most of my applications are actually MVVM applications and in that case it’s not something for the ViewModel, it’s logic that belongs to the view. But how about a Behavior?

I want to give a specific control focus when something happens on something else. So that should be a TargetedTriggerAction<T>, T should be Control, because that’s something you can give focus. How easy can it be?

public class FocusOnEvent : TargetedTriggerAction<Control>
{
    protected override void Invoke(object parameter)
    {
        Target.Focus();
    }
}

Is that all? Yes it is, or actually, I want to make it even easier, add the default trigger using the DefaultTriggerAttribute. Default should be the Loaded event, so let’s add that single line.

[DefaultTrigger(typeof(FrameworkElement), typeof(EventTrigger), "Loaded")]
public class FocusOnEvent : TargetedTriggerAction<Control>
{
    protected override void Invoke(object parameter)
    {
        Target.Focus();
    }
}

Now we have this easy code, how do we use it? Just add a little bit of xaml to your page / control, just like any other behavior.

<i:Interaction.Triggers>
    <i:EventTrigger>
        <Behaviors:FocusOnEvent TargetName="TitleTextBox" />
    </i:EventTrigger>
</i:Interaction.Triggers>

Some second thoughts, is it required to take the Safe event Detachment base class for Windows Phone Behaviors by Joost van Schaik into consideration? No it’s not required, because we’re not manually attaching handlers to the events, that’s all done by the TargetedTriggerAction itself. Hope you guys think this little bit of code is useful.