Enable ApplicationBarMenuItem implementing MVVM approach in Windows Phone 7

Tags: C#, .NET, WP7

Tags: .NET, C#, WP7

This article will explain how to enable or disable an ApplicationBarMenuItem in Windows Phone 7 from a ViewModel object using MVVM pattern.

Suppose we have a page with a check box with the name Enabled and a menu item. When we click on the Enabled check box the Menu Item should enable or disable according to the checkbox status: when the checkbox is enabled the menu is enabled and vice-versa.

This is a trivial task if you add the code behind the view. But how about the cases when we need this from a ViewModel object. The reason for this is that we can have some logic in our ViewModel which dictates whether the Menu Item should be enabled or disabled. For example, the count of the checked items in a ListBox.

This implementation is not straightforward because you can’t bind the MenuItem to an ICommand as it is not a dependency object.

The easiest way will be to write a code behind event handler. In this case the ViewModel will need to have a reference to the View which is not a good practice. To avoid this we will raise an event in the ViewModel and View will respond to that event. This is not the best way but at least the ViewModel doesn’t need to know about the View.

I will create a property in the ViewModel (IsCheckBoxSelected) and a dependency property in the View (State) which is bind to the property in the ViewModel.

The check box is binded to the IsCheckBoxSelected property. When the check box changes its status it updates the IsMenuEnabled property which is binded to the dependency property in the ViewModel:

public bool IsCheckBoxSelected
{
    get { return _isCheckBoxSelected; }
    set
    {
        if (_isCheckBoxSelected == value) return;
                
        _isCheckBoxSelected = value;
                
        IsMenuEnabled = _isCheckBoxSelected;
        OnPropertyChanged("IsCheckBoxSelected");
    }
}

public bool IsMenuEnabled
{
    get
    {
        return _isMenuEnabled;
    }
    set
    {
        if (_isMenuEnabled == value) return;

        _isMenuEnabled = value;
        OnPropertyChanged("IsMenuEnabled");
    }
}

We need to bind the dependency property in the ViewModel code behind:

ApplicationBarMenuItem menuItem = ApplicationBar.MenuItems[0] as ApplicationBarMenuItem;

MenuStateControl menuStateControl = new MenuStateControl(menuItem);
Binding binding = new Binding
    {
        Path = new PropertyPath("IsMenuEnabled"), 
        Source = DataContext
    };

menuStateControl.SetBinding(MenuStateControl.StateProperty, binding);

Here we bind the IsMenuEnabled property to the State dependency property.

Below is the code for the dependency property:

public class MenuStateControl : UserControl
{
    private static ApplicationBarMenuItem _menuItem;
    public MenuStateControl(ApplicationBarMenuItem menuItem)
    {
        _menuItem = menuItem;
    }

    public bool State
    {
        get { return (bool)GetValue(StateProperty); }
        set { SetValue(StateProperty, value); }
    }

    public static readonly DependencyProperty StateProperty = DependencyProperty.Register(
    "State", typeof(string), typeof(MenuStateControl), new PropertyMetadata(String.Empty, OnCallBack));


    private static void OnCallBack(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue == null) return;
        bool isEnabled;
        if (Boolean.TryParse(e.NewValue.ToString(), out isEnabled))
        {
            _menuItem.IsEnabled = isEnabled;
        }

    }

}

 

The source code is available at GitHub https://github.com/ralbu/MenuItemMvvmWP7

Conclusion

This is not the best way to implement it but it allows the separation of concerns.

Comments

comments powered by Disqus