Customizing the map menu

The MapControl class contains a menu that can be customized in the same way that the application menu is. Like MobileApplication, the MapControl class has a MenuItems property:

public partial class  MapControl
{
  public ObservableCollection<object> MenuItems { get; }
}

Extending the map menu on the View Map page

To customize the menu of a particular map control, you first need to determine which map control you want to customize and get a reference to it. For this example, you will extend the menu of the map control on the View Map page. This particular map control is part of ViewMapPage, which is part of ViewMapTask. Start by getting ViewMapTask from the project:

ViewMapTask  viewMapTask = (ViewMapTask)MobileApplication.Current.Project.Tasks.GetFirstExtensionOfType(typeof(ViewMapTask));

Next, ViewMapPage is accessible as a property on ViewMapTask:

ViewMapPage viewMapPage = viewMapTask.ViewMapPage;

Finally, MapControl is accessible via a property on ViewMapPage:

MapControl mapControl = viewMapPage.MapControl;

Now you can customize the map control's menu similar to the application menu.

class MyExtension :  ProjectExtension
{
  private MapControl _mapControl;
 
  protected override void OnOwnerInitialized()
  {
    ViewMapTask viewMapTask = (ViewMapTask)MobileApplication.Current.Project.Tasks.GetFirstExtensionOfType(typeof(ViewMapTask));
    if (viewMapTask == null)
      return;
     
    _mapControl = viewMapTask.ViewMapPage.MapControl;
 
    MenuItem menuItem = new MenuItem();
    menuItem.Header = "Hello";
    menuItem.Command = new RelayCommand(param => this.MyMapCommandExecute());
    _workListMapControl.MenuItems.Add(menuItem);
  }
 
  private void MyMapCommandExecute()
  {
    StringBuilder builder = new StringBuilder();
    builder.AppendLine("You clicked my menu item!");
    builder.AppendLine(_mapControl.GetExtent().ToString());
    System.Windows.MessageBox.Show(builder.ToString());
  }
}

Another way to write this example is to use WPF RoutedUICommand instead of RelayCommand. One benefit of using RoutedUICommand is that the Execute delegate of the command binding is passed the control that raised the event as a parameter. This means, as in the example above, you do not need to retain a reference to MapControl as a member variable. This enables you to add menu items to multiple menus that all reference the same RoutedUICommand.

Here is the above example rewritten using RoutedUICommand:

class MyExtension :  ProjectExtension
{
  // Our (static) RoutedUICommand
  public static readonly RoutedUICommand MyRoutedMapCommand = new RoutedUICommand("Hello", "MyRoutedMapCommand", typeof(MyExtension));
 
  protected override void OnOwnerInitialized()
  {
    ViewMapTask viewMapTask = (ViewMapTask)MobileApplication.Current.Project.Tasks.GetFirstExtensionOfType(typeof(ViewMapTask));
    if (task == null)
      return;
     
    MapControl mapControl = viewMapTask.ViewMapPage.MapControl;
 
    // Add a new item to the map control menu in the ViewMapPage
    MenuItem menuItem = new MenuItem();
    menuItem.Header = "Hello";
    menuItem.Command = MyRoutedMapCommand;
    menuItem.CommandTarget = mapControl;
    mapControl.MenuItems.Add(menuItem);
 
    // Now add a command binding for our RoutedUICommand to the map control
    CommandBinding commandBinding = new CommandBinding(MyRoutedMapCommand);
    commandBinding.Executed += new ExecutedRoutedEventHandler(RoutedWorkListPageCommandBinding_Executed);
    mapControl.CommandBindings.Add(commandBinding);
  }
 
  void RoutedWorkListPageCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
  {
    MapControl mapControl = sender as MapControl;
 
    StringBuilder builder = new StringBuilder();
    builder.AppendLine("You clicked my menu item!");
    builder.AppendLine(mapControl.GetExtent().ToString());
    System.Windows.MessageBox.Show(builder.ToString());
  }
}

The above example could easily be extended to create and add another menu item associated with the same RoutedUICommand and add it to a different map control menu on a different page, but use the same Executed handler (RoutedWorkListPageCommandBinding_Executed).

Extending all map menus

The application framework has the ability to allow the menu of all map control instances to be customized. MapControl has a static event (CreatingMapControlMenuItems) that is raised each time an instance of MapControl creates its collection of menu items. The EventArgs parameter passed to this event contains a reference to the MapControl instance that is creating its MenuItems collection.

public static  event EventHandler<CreatingMapControlMenuItemsEventArgs>  CreatingMapControlMenuItems;
public class CreatingMapControlMenuItemsEventArgs : EventArgs
{
  public MapControl MapControl { get; }
}

To add a menu item to all map controls, you subscribe to the CreatingMapControlMenuItems event and update the MenuItems collection of the MapControl instance passed to the event handler.

class MyExtension :  ProjectExtension
{
  public static readonly RoutedUICommand RoutedGlobalMapCommand =
    new RoutedUICommand("Hello ", "RoutedGlobalMapCommand", typeof(MyExtension));
 
  public MyExtension()
  {
    ESRI.ArcGIS.Mobile.Client.Controls.MapControl.CreatingMapControlMenuItems +=
      new EventHandler<CreatingMapControlMenuItemsEventArgs>(MapControl_CreatingMapControlMenuItems);
  }
 
  void MapControl_CreatingMapControlMenuItems(object sender, CreatingMapControlMenuItemsEventArgs e)
  {
    MenuItem menuItem = new MenuItem();
    menuItem.Header = "Hello";
    menuItem.Command = RoutedGlobalMapCommand;
    menuItem.CommandTarget = e.MapControl;
    e.MapControl.MenuItems.Add(menuItem);
 
    CommandBinding commandBinding = new CommandBinding(RoutedGlobalMapCommand);
    commandBinding.Executed +=new ExecutedRoutedEventHandler(RoutedGlobalMapCommandBinding_Executed);
    e.MapControl.CommandBindings.Add(commandBinding);
  }

  void RoutedGlobalMapCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
  {
    // Similar to previous examples
  }
 
  protected override void Uninitialize()
  {
    // Stop listening to events
    ESRI.ArcGIS.Mobile.Client.Controls.MapControl.CreatingMapControlMenuItems -=
      new EventHandler<CreatingMapControlMenuItemsEventArgs>(MapControl_CreatingMapControlMenuItems);
  }
}

9/20/2011