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); } }