Adding a Menu Item

3/30/2010 8:25 PM
You can subscribe to this wiki article using an RSS feed reader.


The Existing Workbench Menu

The SoapBox.Core Workbench already comes with the following menu structure:

  • File
    • Exit
  • Edit
  • View
    • ToolBars >  (automatically lists all ToolBars added so the user can hide and show each one)
  • Tools
    • Options...  (already hooked up to show the Options Dialog.  Delete SoapBox.Core.Options.dll and this will disappear)
  • Window
  • Help

However, menu items without any children won't show up, so you may not see all of them.

Example: Adding an Item to the View Menu

Assumes you've already created an Add-In and created a Pad.  This View Menu Item will show that pad when the menu item is clicked.

  1. By convention I've been creating a \Workbench\MainMenu project folder under each Add-In project to put menu items in.  This is optional.
  2. Create a new code file called ViewMenu.cs.  (Since menu item ViewModels are typically so short, I have been putting all the View menu items in one file, but you're welcome to create a ViewMenu subdirectory and put individual class files in there.)
  3. Add the following using statements:
    using SoapBox.Core;
    using System.ComponentModel.Composition;

  4. Adjust the default namespace that Visual Studio creates, and just use YourNamespace.YourSubNamespace.AddInName (I suggest).
  5. Here is the class for a single new Menu Item in the View Menu:
    [Export(SoapBox.Core.ExtensionPoints.Workbench.MainMenu.ViewMenu, typeof(IMenuItem))]
    class ViewMenuShowMyPad: AbstractMenuItem
    {
        public
    ViewMenuShowMyPad()
        {
            ID = "MyPad";

            // insert the new item before the ToolBars submenu
            InsertRelativeToID = "ToolBars";
            BeforeOrAfter = RelativeDirection.Before;

            Header = "My Pad"; // should use:
                               // Resources.Strings.Workbench_MainMenu_View_MyPad
                               // for localization
            ToolTip = "Show My Pad";  // ditto
        }

       
    [Import(SoapBox.Core.Services.Layout.LayoutManager, typeof(ILayoutManager))]
       
    private Lazy<ILayoutManager> layoutManager { get; set; }

       
    [Import(CompositionPoints.Workbench.Pads.MyPad, typeof(MyPad))]
       
    private MyPad myPad { get; set; }

        protected override void Run()
        {
            layoutManager.Value.ShowPad(
    myPad.Value);
        }
    }

Advanced Menu Items

Adding an Icon

You can add an Icon to your menu item easily if you have a bitmap stored in a resource file.  Just call this in your menu item's constructor:

SetIconFromBitmap(Resources.Images.Workbench_Command_MyMenuItemIcon);

The framework will take care of changing the image to grayscale when the command can't be executed.

Checkable

You can make this a checkable menu item with the following changes:

  1. Add this to your constructor:
    IsCheckable = true;
    IsChecked = true; // default value

  2. Add this in your class:
    protected override void OnIsCheckedChanged()
    {
        base.OnIsCheckedChanged();
        // take an action on the check being changed here
    }

Make it a Menu Item Separator

Easily enough, in the constructor, do this:

IsSeparator = true;

Add a Sub Menu

Menu items can have submenus.  Not only that, but these submenus are extension points just like the main menu items.  The easiest way to explain how this works is to show you the File Menu Item:

    [Export(ExtensionPoints.Workbench.MainMenu.Self, typeof(IMenuItem))]
    class FileMenu : AbstractMenuItem, IPartImportsSatisfiedNotification
    {
        public FileMenu()
        {
            ID = SoapBox.Core.Extensions.Workbench.MainMenu.File;
            Header = Resources.Strings.Workbench_MainMenu_File;
        }

        [Import(SoapBox.Core.Services.Host.ExtensionService)]
        private IExtensionService extensionService { get; set; }


        [ImportMany(SoapBox.Core.ExtensionPoints.Workbench.MainMenu.FileMenu,
                           typeof(IMenuItem), AllowRecomposition=true)]
        private IEnumerable<IMenuItem> menu { get; set; }

       
        public void OnImportsSatisfied()
        {
            Items = extensionService.Sort(menu);
        }
    }

Calling extensionService.Sort(...) makes sure that all of the imported sub menu items are ordered according to the InsertRelativeTo and BeforeOrAfter properties.


Tags:
Home: SoapBox Core What's new: Recently changed articles