Windows Phone 7 View Model (MVVM) ApplicationBar
Dec
23
Written by:
12/23/2010 10:12 PM

Using a behavior to dynamically create a Windows Phone 7 ApplicationBar.

I don’t know if the sample attached to this article uses the method that Daniel Vaughan will have in his upcoming book, but the fact that he Tweeted that he had done it, was all that was needed for me to “try” to do it. Either way, you will want to get his book when it comes out because I am sure he will have a polished solution. All I have here is a rough outline on a possible method.
The Problem
At this time, the Windows Phone ApplicationBar does not allow you to bind to it. To manipulate it ,you need to use code behind. This is only a problem if you are using View Model (MVVM) , because you don’t have your code nice and tidy in your View Model like you are used to when coding Silverlight 4 (at this time the Windows Phone 7 uses a version of Silverlight 3).
A Solution

Create a Windows Phone 7 project and add MVVM LIght. MVVM Light contains a RelayComand method to call ICommands, but I already had some code that was using John Papa’s DelegateCommand class, so I am also using that in the sample code. However, you can just use the RelayComand that comes with MVVM Light.

The project has a simple ViewModel.

The ApplicationBarBehavior does all the work:
using System.Windows;
using System.Windows.Input;
using System.Windows.Interactivity;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using System;
using WindowsPhoneDataBoundApplication1;
namespace BehaviorsLibrary
{
[System.ComponentModel.Description("Creates ApplicationBar")]
public class ApplicationBarBehavior : Behavior<PhoneApplicationPage>
{
PhoneApplicationPage ParentPhoneApplicationPage;
ApplicationBarIconButton btnSave;
ApplicationBarIconButton btnDelete;
// ICommandPropertys
#region VisibleICommandProperty
public static readonly DependencyProperty VisibleICommandProperty =
DependencyProperty.Register("VisibleICommand", typeof(ICommand),
typeof(ApplicationBarBehavior), null);
public ICommand VisibleICommand
{
get
{
return (ICommand)base.GetValue(VisibleICommandProperty);
}
set
{
base.SetValue(VisibleICommandProperty, value);
}
}
#endregion
#region InVisibleICommandProperty
public static readonly DependencyProperty InVisibleICommandProperty =
DependencyProperty.Register("InVisibleICommand", typeof(ICommand),
typeof(ApplicationBarBehavior), null);
public ICommand InVisibleICommand
{
get
{
return (ICommand)base.GetValue(InVisibleICommandProperty);
}
set
{
base.SetValue(InVisibleICommandProperty, value);
}
}
#endregion
protected override void OnAttached()
{
base.OnAttached();
ParentPhoneApplicationPage = AssociatedObject;
ParentPhoneApplicationPage.ApplicationBar = new ApplicationBar();
ParentPhoneApplicationPage.ApplicationBar.IsVisible = true;
ParentPhoneApplicationPage.ApplicationBar.IsMenuEnabled = true;
// Save Button
btnSave = new ApplicationBarIconButton(new Uri("/icons/appbar.save.rest.png", UriKind.Relative));
btnSave.Text = "Save";
btnSave.Click += new EventHandler(btnSaveTrip_Click);
ParentPhoneApplicationPage.ApplicationBar.Buttons.Add(btnSave);
// Delete Button
btnDelete = new ApplicationBarIconButton(new Uri("/icons/appbar.delete.rest.png", UriKind.Relative));
btnDelete.Text = "Delete";
btnDelete.Click += new EventHandler(btnDelete_Click);
ParentPhoneApplicationPage.ApplicationBar.Buttons.Add(btnDelete);
// Set-up Commands
VisibleICommand = new DelegateCommand(VisibleCommand, CanVisibleCommand);
InVisibleICommand = new DelegateCommand(InVisibleCommand, CanInVisibleCommand);
}
protected override void OnDetaching()
{
base.OnDetaching();
// Remove event handlers
btnSave.Click -= new EventHandler(btnSaveTrip_Click);
btnDelete.Click -= new EventHandler(btnDelete_Click);
}
// Button Events
#region btnDelete_Click
void btnDelete_Click(object sender, EventArgs e)
{
MainViewModel VM = (MainViewModel)ParentPhoneApplicationPage.DataContext;
VM.SampleMessageCommand.Execute("Delete Clicked");
}
#endregion
#region btnSaveTrip_Click
void btnSaveTrip_Click(object sender, EventArgs e)
{
MainViewModel VM = (MainViewModel)ParentPhoneApplicationPage.DataContext;
VM.SampleMessageCommand.Execute("Save Clicked");
}
#endregion
// Commanding
#region VisibleICommand
public void VisibleCommand(object param)
{
ParentPhoneApplicationPage.ApplicationBar.IsVisible = true;
}
private bool CanVisibleCommand(object param)
{
return true;
}
#endregion
#region InVisibleICommand
public void InVisibleCommand(object param)
{
ParentPhoneApplicationPage.ApplicationBar.IsVisible = false;
}
private bool CanInVisibleCommand(object param)
{
return true;
}
#endregion
}
}
Hooking It Up

We Add two Buttons to the page.

We drop the Behavior on the PhoneApplicationPage node in the Objects and Timeline window.
We then wire up each Button. Here are the steps to wire-up the MakeInvisible Button to the inVisibleICommand:






No Code Behind?
All this method really does is move code that you would have put in code behind to a Behavior. For some, you may not care. The purpose here was only to show you what is possible.
You can download the sample code at this link.
3 comment(s) so far...
Re: Windows Phone 7 View Model (MVVM) ApplicationBar
When I first saw that the AppBar stuff was not MVVM-able, I was very upset. It really shows the people designing it didnt have a CLUE about how people use Silverlight. Nice little work around you have though. I guess we just have to add this to the MASSIVE list of "stupid stuff about Silverlight/WP7 we have to work around" list.
By Brad on
12/29/2010 11:04 AM
|
Re: Windows Phone 7 View Model (MVVM) ApplicationBar
@Brad - Thanks for the comment. I just hope I have provided something useful.
By Michael Washington on
12/29/2010 11:04 AM
|
Re: Windows Phone 7 View Model (MVVM) ApplicationBar
Thanks! I'll try to use it in my project.
By Niki on
1/19/2011 5:09 AM
|