上下文菜单按钮在 Excel 加载项中触发一次

context-menu button fires once in Excel Add-In

我的上下文菜单按钮只触发一次。 btn 对象在启动时死亡。我该如何解决?

如何这么早修复调用对象?

public partial class ThisAddIn
{
    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {                        
        PicPaste btn = new PicPaste(this.Application);}

class PicPaste
{
    private Excel.Application application;
    private Office.CommandBarButton   picpasteMenuItem;
    public PicPaste(Excel.Application app)
    {
        application = app;
        CreatePicpasteBtn();
    }

    public  void CreatePicpasteBtn()
    {
        Office.MsoControlType contextMenuItem = Office.MsoControlType.msoControlButton;
        Office.CommandBar commandBarCell = application.CommandBars["Cell"];
        picpasteMenuItem = commandBarCell.Controls.Add(contextMenuItem, Type.Missing, Type.Missing, 5, true) 
            as Office.CommandBarButton;

        if (picpasteMenuItem != null)
        {
            picpasteMenuItem.Style = Office.MsoButtonStyle.msoButtonCaption;
            picpasteMenuItem.Caption = "Вставить изображение в коммент";
            picpasteMenuItem.Click += new Office._CommandBarButtonEvents_ClickEventHandler(
                PicPasteMenuItemClick);
        }
    }

    private static void PicPasteMenuItemClick(Office.CommandBarButton Ctrl, ref bool CancelDefault)
    {
       ...some code here

    }
}

问题是您在 method/event 中声明和实例化对象 PicPaste btn = new PicPaste(this.Application);。这意味着它将适用于此程序;当程序完成时它超出范围,最终将被垃圾收集。

您需要在 class 级别[=20] 声明 在您的加载项的生命周期内应该存在的任何对象=] - 在任何程序之外。然后它们将保留在范围内,直到您的加载项被卸载。

因此,例如:

public partial class ThisAddIn
{
  PicPaste btn = null;
  private void ThisAddIn_Startup(object sender, System.EventArgs e)
  {                        
    btn = new PicPaste(this.Application);
  }

看起来 PicPaste 实例的范围受到某种限制。但该方法是正确的——将源对象定义在 class 级别,以防止它被 GC 从堆中清除。尝试使用将存储在加载项 class 级别或类似内容的控件列表:

PicPaste btn = null;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{                        
    btn = new PicPaste(this.Application);
}