Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

Unfortunately, in the current version of the Windows Phone 7 Silverlight framework, it is not possible to attach any command on the ApplicationBarMenuItem and ApplicationBarButton controls. These two controls appear in the Application Bar, for example with the following markup:

<phoneNavigation:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar x:Name="MainPageApplicationBar">
        <shell:ApplicationBar.MenuItems>
            <shell:ApplicationBarMenuItem 
                Text="Add City" />
            <shell:ApplicationBarMenuItem 
                Text="Add Country" />
        </shell:ApplicationBar.MenuItems>
        <shell:ApplicationBar.Buttons>
            <shell:ApplicationBarIconButton 
                IconUri="/Resources/appbar.feature.video.rest.png" />
            <shell:ApplicationBarIconButton 
                IconUri="/Resources/appbar.feature.settings.rest.png" />
            <shell:ApplicationBarIconButton 
                IconUri="/Resources/appbar.refresh.rest.png" />
        </shell:ApplicationBar.Buttons>
    </shell:ApplicationBar>
</phoneNavigation:PhoneApplicationPage.ApplicationBar>

This code will create the following UI:


Application bar, collapsed


Application bar, expanded

ApplicationBarItems are not, however, controls. A quick look in MSDN shows the following hierarchy for ApplicationBarMenuItem, for example:

Unfortunately, this prevents all the mechanisms that are normally used to attach a Command (for example a RelayCommand) to a control. For example, the attached behavior present in the class ButtonBaseExtension (from the Silverlight 3 version of the MVVM Light toolkit) can only be attached to a DependencyObject. Similarly, Blend behaviors (such as EventToCommand from the toolkit’s Extras library) needs a FrameworkElement to work.

Using code behind

The alternative is to use code behind. As I said in my MIX10 talk, the MVVM police will not take your family away if you use code behind (this quote was actually suggested to me by Glenn Block); the code behind is there for a reason. In our case, invoking a command in the ViewModel requires the following code:

In MainPage.xaml:

<shell:ApplicationBarMenuItem Text="My Menu 1"
    Click="ApplicationBarMenuItemClick"/>

In MainPage.xaml.cs

private void ApplicationBarMenuItemClick(
    object sender, 
    System.EventArgs e)
{
    var vm = DataContext as MainViewModel;
    if (vm != null)
    {
        vm.MyCommand.Execute(null);
    }
}

Conclusion

Resorting to code behind to bridge the gap between the View and the ViewModel is less elegant than using attached behaviors, either through an attached property or through a Blend behavior. It does, however, work fine. I don’t have any information if future changes in the Windows Phone 7 Application Bar API will make this easier. In the mean time, I would recommend using code behind instead.

 

Print | posted on Friday, April 09, 2010 10:40 AM

Feedback

# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by Mark Monster at 5/13/2010 12:01 AM Gravatar
Hi Laurent,

Is there any change in the support for binding to ApplicationBarItems planned by you?

-
Mark Monster

# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by Laurent at 5/13/2010 1:12 AM Gravatar
Hey Mark,

Unfortunately there is not much I can do: binding, commanding, animations and all the wonderful features of Silverlight very much depend on the Dependency property system. If the UI element is not a dependency object (like in the case of Application Bar), then we cannot bind to it and must resort to event handling, as shown in this article. I did contact the team and asked them about this, but didn't get a reply yet.

Cheers,
Laurent

# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by decang at 7/16/2010 4:25 AM Gravatar
Hi Laurent,
I am working toward using your toolkit for my WP7 applicaiton. It is a great tool, BTW.

Do you have new update about the commanding since the latest WP7 tool beta release (7/12)?

Thanks.

# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by Indrajit (Indy) at 8/29/2010 1:08 AM Gravatar
Hi Laurent,

I have been working with MVVMLight for several Windows Phone 7 projects. I am using your approach explained above to invoke a command in the viewmodel from a button in the ApplicationBar. I have a WP7 application where one of the two buttons need to be disabled under certain conditions. Since the "IsEnabled" property of "ApplicationBarIconButton" is not bindable, I use the click event handler to check for the conditions and set the IconButton's IsEnabled to true or false.

Ideally, I would have liked the ViewModel to invoke a callback on the View (View's code-behind), that will set the IsEnabled property to true/false, after I raised the command from within the event handler of the IconButton. Is there a pattern in MVVM / MVVMLight to do this? I understand if I do this, I will be coupling the ViewModel with the View, which is not good for several reasons. What is your recommendation?

Many thanks for the the wonderful articles and the superb framework, it rocks!!

Cheers,
indyfromoz

# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by Laurent Bugnion at 8/29/2010 1:18 AM Gravatar
Hi,

One thing I was thinking of is to have a property on the VM, and to have another dependency property on the View that you bind to the VM's property (in the View's constructor). By handling the PropertyChangedCallback in the View's DP, you can go ahead and set the ApplicationBar's IsEnabled property. Not the cleanest, but at least the VM does not need to know about the View in this manner.

Makes sense?

Cheers,
Laurent

# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by Indrajit (Indy) at 8/29/2010 1:24 AM Gravatar
Hi Laurent,

Many thanks for the quick reply, I can't thank you enough! At this time of the night (11:15PM, Australia), there is no one to talk & discuss such things.

Your suggestion makes perfect sense. I was looking for patterns to do this and of course, the best way to do it. I think this is the best way to have decoupled View and ViewModel and at the same time, also let the ViewModel set the IsEnabled property through the callback.

Excellent! Thanks again.

indyfromoz

# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by Ryan at 1/6/2011 8:52 AM Gravatar
Can you post an example of this (particularly the view code)? I have a property "IsButtonEnabled" on my VM and NotifyProperty is fired for it whenever properties affecting whether it is enabled are changed. I'm not sure on how you would bind this in the view and handle the notifypropertychanged to set the IsEnabled of the appbar button/menu item there.

# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by Rob Davis at 5/18/2011 10:57 AM Gravatar
the way to make everything bindable is to create dependency properties for all the properties on the application bar, luckily this has been done for us(Phone7.Fx.Preview) and here is a detailed guide for using it with MVVM Light.
I bound the bar visibility, button text, button enabled and button click command all with ease.
Only down side is the wrapper control has to sit in the LayoutRoot instead of outside it, but I have not seen any problem with that.

# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by Rob Davis at 5/18/2011 10:58 AM Gravatar
that link being http://geekswithblogs.net/mbcrump/archive/2011/02/22/attaching-a-command-to-the-wp7-application-bar.aspx

# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by Luke at 10/8/2011 5:37 PM Gravatar
The reason for the lack of Command support is possibly because Expression Blend adds the data context object (view model) as a resource of the page, and since the application bar is a component of the page, the data context wouldn't be available to it at the time of its initialization. That's my theory.

# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by Laurent at 10/8/2011 5:43 PM Gravatar
Mmmh no, the reason for the lack of command in the app bar is because the app bar is a system component that the Silverlight application is interoperating with. Blend has nothing to do with it, really.

# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by Luke at 10/8/2011 6:52 PM Gravatar
Looking at the API, I can see what you mean now; I originally assumed the ApplicationBar was an abstraction for XAML use, but it seems not.

Even so, and unless I'm doing something wrong, setting the DataContext property on the Page to a resource in Page.Resources doesn't work, so I'm not sure how it could get at the view model even if MS made it a DependencyObject.

# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by Luke at 10/8/2011 7:02 PM Gravatar
Thinking about it, I guess the DataContext would be available as a dp on the ApplicationBar object which I assume can be pointed at a Page resource if they're set before in the XAML file.

Anyway, its all moot. Maybe I could build my own set of 'abstraction' controls if I was too worried about my family being taken away. Not that I don't care for my family, its just that she hoovers while I'm concentrating on comments in blogs.

# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by Laurent Bugnion at 10/8/2011 7:15 PM Gravatar
XAML is parsed sequentially, so you can set the DataContext to an item in resources only if the item has been parsed already. For instance, this does not work:

<UserControl ...
DataContext="{Binding Source={StaticResource MyObject}}">

<UserControl.Resources>
<vm:MyObject x:Key="MyObject" />
</UserControl.Resources>


However this works:

<UserControl.Resources>
<vm:MyObject x:Key="MyObject" />
</UserControl.Resources>

<UserControl.DataContext>
<Binding Source={StaticResource MyObject}" />
</UserControl.DataContext>

In MVVM Light, I introduced the concept of ViewModelLocator, which makes the bindings easier.

For more information, check the sessions I gave at MIX in 2010 and 2011:
http://www.galasoft.ch/mvvmvideo1
http://www.galasoft.ch/mvvmvideo2
http://www.galasoft.ch/mvvm

Cheers,
Laurent


# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by Luke at 10/8/2011 7:51 PM Gravatar
Ahh, Laurent. I've been using your fabulous little framework for over a year ;)

# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by Laurent at 10/8/2011 9:27 PM Gravatar
How nice :-) sorry I didn't know!

Cheers
Laurent

# re: Using commands with ApplicationBarMenuItem and ApplicationBarButton in Windows Phone 7

left by Laurent at 10/8/2011 9:27 PM Gravatar
How nice :-) sorry I didn't know!

Cheers
Laurent
Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification: