I want my add-in to create a new menu item in the View menu and then call some code in my add-in when the user clicks on the menu item.

asked 01 Jun '10, 20:59

Scott%20Whitlock's gravatar image

Scott Whitlock ♦♦
696262833
accept rate: 50%

edited 01 Jun '10, 21:00


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 WorkbenchMainMenu 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:

(Please see Appendix A below...)

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:

Add this to your constructor:

IsCheckable = true;
IsChecked = true; // default value

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.

link

answered 01 Jun '10, 21:03

Scott%20Whitlock's gravatar image

Scott Whitlock ♦♦
696262833
accept rate: 50%

edited 01 Jun '10, 21:19

Appendix A:

(I had some problems with code formatting and had to move it down here.)

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

answered 01 Jun '10, 21:16

Scott%20Whitlock's gravatar image

Scott Whitlock ♦♦
696262833
accept rate: 50%

edited 01 Jun '10, 21:17

I believe the line --> private MyPad myPad { get; set; } should be --> private Lazy<mypad> myPad { get; set; }

(07 Sep '11, 23:28) granthes
Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "Title")
  • image?![alt text](/path/img.jpg "Title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Tags:

×23
×7

Asked: 01 Jun '10, 20:59

Seen: 36,772 times

Last updated: 07 Sep '11, 23:28

powered by OSQA