Command Bar with Visual Studio Tools for Office

Developing for Microsoft Office with VSTO is fantastic, I mean, when the only other option is VBA. And that was basically the main reason I ended up working with VSTO in the first place.

A problem I had right in the beginning of my adventure was with the user interaction with the add-in. It was a simple custom toolbar with buttons, nothing fancy, but sometimes after using the add-in for a while the buttons would just randomly stop responding.

The bug was in the code that created the command bar and attached the event handlers. In order to configure and add the click event handler I was using a local variable to reference the newly added command bar button. Being local this variable would later be collected by the GC resulting in the loss of the event handler. So don’t forget… specify all command bar button variables at the add-in level to prevent them from being garbage collected.

You can check this behavior in the following example:

using System.Windows.Forms;
using Office = Microsoft.Office.Core;

public partial class ThisAddIn
{
    private Office.CommandBar bar;

    private Office.CommandBarButton showMsgCorrect;

    private void ThisAddIn_Startup(object sender, EventArgs e)
    {
        bar = Application.CommandBars.Add(
            "Example Bar",
            Office.MsoBarPosition.msoBarTop,
            false,
            true);

        // Do this
        showMsgCorrect = (Office.CommandBarButton)bar.Controls.Add(
            Office.MsoControlType.msoControlButton,
            missing,
            missing,
            missing,
            missing);

        showMsgCorrect.Caption = "It Works";
        showMsgCorrect.TooltipText = "Will always work";
        showMsgCorrect.Style = Office.MsoButtonStyle.msoButtonCaption;
        showMsgCorrect.Click += new Office._CommandBarButtonEvents_ClickEventHandler(button_Click);

        // Don't do this - Garbage collection will break it
        Office.CommandBarButton showMsgIncorrect;

        showMsgIncorrect = (Office.CommandBarButton)bar.Controls.Add(
            Office.MsoControlType.msoControlButton,
            missing,
            missing,
            missing,
            missing);

        showMsgIncorrect.Caption = "Will Stop Working";
        showMsgIncorrect.TooltipText = "Will stop working";
        showMsgIncorrect.Style = Office.MsoButtonStyle.msoButtonCaption;
        showMsgIncorrect.Click += new Office._CommandBarButtonEvents_ClickEventHandler(button_Click);

        bar.Visible = true;
    }

    private void ThisAddIn_Shutdown(object sender, EventArgs e)
    {
    }

    void button_Click(Office.CommandBarButton Ctrl, ref bool Cancel)
    {
        MessageBox.Show(
            "Hello World!",
            string.Empty,
            MessageBoxButtons.OK,
            MessageBoxIcon.Information);

        GC.Collect();
    }

    #region VSTO generated code

    private void InternalStartup()
    {
        this.Startup += new System.EventHandler(ThisAddIn_Startup);
        this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
    }

    #endregion
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s