I’d like to share today’s experience of adding buttons to the solution and project context menus in Visual Studio 2005’s Solution Explorer window. (I ended up with this)
Seems like everything related to Visual Studio extensibility is overly complicated, but unlike other extensibility tasks, this one is rather simple.
Step 1 will be to find our CommandBar.
The CommandBar is our target where we would like to place our buttons. In my case, I wanted to add a button to the context menu that pops up when you right-click on a solution or project. You can retrieve your CommandBar object from the applicationObject.CommandBars collection by specifying its name.
1: CommandBars commandBars = ( CommandBars )applicationObject.CommandBars;
2: CommandBar commandBar = commandBars[ “Solution” ];
“Solution” represents the context menu that pops up when you right-click solutions in the Solution Explorer and “Project” represents the one for projects.
In step 2 we will create the actual button.
The type of this button control is CommandBarButton. In spite of what you might think, you can’t just initialize it by using new CommandBarButton(), you have to get your instance by calling the Add method on your CommandBar.
Here is how the CommandBar.Add method looks like: (don’t copy & paste this code)
CommandBarControl Add(object Type, object Id, object Parameter, object Before, object Temporary);
Don’t ask me why everything is object based, I’m guessing it has something to do with the fact that the entire model is COM based. oh well.
The CommandBarButton is created this way:
1: CommandBarButton button = ( CommandBarButton )commandBar.Controls.Add( MsoControlType.msoControlButton, Missing.Value, Missing.Value, 1, true );
2: button.Caption = “My Button”;
You can compile your solution and run it, you will be able to see your button in the Solution Explorer.
This is all good, but a button that doesn’t do anything is really not that handy nowadays so we’ll have to subscribe to its click event.
Step 3: Doing stuff when the button is clicked.
Well, you guessed it, we can’t do that simply by registering to the button’s OnClick event, cause there isn’t one. We have to register through the button’s CommandBarEvents object.
The CommandBarEvents class exposes the Click event for your button. Here’s how to add some event handling code for the Click event:
1: CommandBarEvents myButtonEvents = ( CommandBarEvents )applicationObject.Events.get_CommandBarEvents( myButton );
2: myButtonEvents.Click +=
3: delegate( object CommandBarControl, ref bool Handled, ref bool CancelDefault )
5: // TODO: Handle the Click event.
6: Handled = true;
And now for a tricky part: since you get your instance of CommandBarEvents inside the scope of a method, when the method ends, the Garbage Collector collects it, leaving all the event handlers orphaned. Unless you keep your instance safe from the jaws of the mighty Garbage Collector, your buttons will not respond to clicks.
To do so, just keep your CommandBarEvents instance(s) as member fields of your class. Once your class is disposed, they will be disposed as well.