OpenLightGroup Blog

rss

Blogs from OpenLightGroup.net


Windows Phone 7 View Model (MVVM) ApplicationBar

image

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

 

image

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

image

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.

image

The project has a simple ViewModel.

image

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

image

We Add two Buttons to the page.

image

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:

image

image

image

image

image

image

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.





Comments are closed.
Showing 3 Comments
Avatar  Niki 7 years ago

Thanks! I'll try to use it in my project.

Avatar  Michael Washington 7 years ago

@Brad - Thanks for the comment. I just hope I have provided something useful.

Avatar  Brad 7 years ago

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.