保存在 word VSTO 中的按钮

Button on being saved in word VSTO

我有这段代码:

private void button2_Click(object sender, RibbonControlEventArgs e)
{
    Microsoft.Office.Tools.Word.Controls.Button salesButton;
    Document vstodoc = Globals.Factory.GetVstoObject(Globals.ThisAddIn.Application.ActiveDocument);
    Microsoft.Office.Interop.Word.Application objApplication = Globals.ThisAddIn.Application;
    Microsoft.Office.Interop.Word.Selection objSelection = objApplication.Selection;
    Microsoft.Office.Interop.Word.Range objRange = objSelection.Range;
    salesButton = vstodoc.Controls.AddButton(objRange, 20, 20, "salesButton");
    salesButton.Text = "Calculate Total Sales";
}

当我点击按钮时,Word 文档中插入了一个按钮,但当我保存它并尝试重新打开 Word 文档时,按钮不再存在。

保存Word文档之前:

保存Word文档后:

我找到了解决这个问题的方法。

1。所有动态创建的主机控件都与其事件断开连接,并且它们失去了数据绑定功能。您可以在解决方案中添加代码,以便在重新打开文档时重新创建宿主控件 (Dynamic MsControl)

步骤 1 创建一个单词插件

步骤 2 添加对项目的引用

Microsoft.Office.Tools.Word.v4.0.Utilities.dll

步骤 3 向项目添加功能区

  • 现在你的项目应该是这样的

步骤 4 转到您的 ThisAddsIn.cs 文件

 public partial class ThisAddIn
    {
 
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
        }

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

        #region VSTO generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }
        
        #endregion
    }


在上面新建一个方法class命名为WhenRibionBtnIsClicked()

  private Microsoft.Office.Tools.Word.Controls.Button button = null;//decalre a global varible
  internal void WhenRibionBtnIsClicked()
  {
    Document vstoDocument = Globals.Factory.GetVstoObject(this.Application.ActiveDocument);
    Word.Selection selection = this.Application.Selection;
    if (selection != null && selection.Range != null)
    {
      string name ="myBtn";
      Button button = new Button();
      button.Click += new EventHandler(Generatedbtn_Click);
      button = vstoDocument.Controls.AddButton(selection.Range, 100, 30, name);
     
      button.Text = "I am A Generated Button";
      button.Name = name;
     
     /*this part is done so that when the document is closed the button state is saved in the document property*/
      string startPosition = selection.Range.Start.ToString();
      string endPosition = selection.Range.End.ToString();
      //create a custom property to save infornmation needed to recreate the button
    Microsoft.Office.Core.DocumentProperties properties =(DocumentProperties)Globals.ThisAddIn.Application.ActiveDocument.CustomDocumentProperties;

//save the start range pos
   if (properties.Cast<DocumentProperty>().Where(c => c.Name == "startPosition").Count() == 0)
    {
      properties.Add("startPosition", false, MsoDocProperties.msoPropertyTypeString, startPosition);
    }
    else{
          properties["startPosition"].Value = startPosition;
          Globals.ThisAddIn.Application.ActiveDocument.Saved = false; //important somtimes
        }

      //save the End range pos
   if (properties.Cast<DocumentProperty>().Where(c => c.Name == "endPosition").Count() == 0)
   {
     properties.Add("endPosition", false, MsoDocProperties.msoPropertyTypeString, endPosition);
   }else
       {
         properties["endPosition"].Value = endPosition;
         Globals.ThisAddIn.Application.ActiveDocument.Saved = false; //important somtimes
       }
   // Store Button Info
   if (properties.Cast<DocumentProperty>().Where(c => c.Name == "btnName").Count() == 0)
     {
      properties.Add("btnName", false, MsoDocProperties.msoPropertyTypeString, name);
     } else
            {
               properties["btnName"].Value = startPosition;
               Globals.ThisAddIn.Application.ActiveDocument.Saved = false; //important somtimes
            }

  if (properties.Cast<DocumentProperty>().Where(c => c.Name == "btnText").Count() == 0)
  {
    properties.Add("btnText", false, MsoDocProperties.msoPropertyTypeString, "I am A Generated Button");
  }else
      {
        properties["btnText"].Value = "I am A Generated Button";
        Globals.ThisAddIn.Application.ActiveDocument.Saved = false; //important somtimes                    
      }
   //you can add more custom properties just like how i added start and end strings
    }//end of if selection != null && selection.Range != null

  }//end of WhenRibionBtnIsClicked Method

步骤 5 为word文件中已经生成的按钮创建按钮点击事件

 void Generatedbtn_Click(object sender, EventArgs e)
 {
    MessageBox.Show("I have Been Clicked :-O");
 }

步骤 6 现在在 Ribbon.cs 文件中 获取功能区中创建的按钮的点击事件并将其指向上面创建的 class

  private void btnTest_Click(object sender, RibbonControlEventArgs e)
        {
            Globals.ThisAddIn.WhenRibionBtnIsClicked();
        }

所以现在当你 运行 它时你应该能够看到以下内容:

然而你将面临的问题是当你保存文档时这个东西被删除了所以你必须做的是在单词开始时重新创建这个按钮并使用你存储的属性来获取按钮关于按钮的状态或其他信息

步骤 7 转到函数 ThisAddIn_Startup

private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
  Word.Application wb;
  wb = this.Application;
  if (wb.Documents.Count > 0)
   {
      String queryResult_StartPosition = String.Empty;
      String queryResult_EndPosition = String.Empty;
      String queryResult_btnName = String.Empty;
      String queryResult_btnText = String.Empty;
      Microsoft.Office.Core.DocumentProperties properties = (DocumentProperties)Globals.ThisAddIn.Application.ActiveDocument.CustomDocumentProperties;

     //get doc info about start pos
     if (properties.Cast<DocumentProperty>().Where(c => c.Name == "startPosition").Count() > 0)
    {
        queryResult_StartPosition = properties["startPosition"].Value;
    }
    else
       {
         queryResult_StartPosition = String.Empty;
       }
       //get doc info about end pos
                
    if (properties.Cast<DocumentProperty>().Where(c => c.Name == "endPosition").Count() > 0)
  {
    queryResult_EndPosition = properties["endPosition"].Value;
  }
   else
       {
         queryResult_EndPosition = String.Empty;
       }
   //get info about btn name
    if (properties.Cast<DocumentProperty>().Where(c => c.Name == "btnName").Count() > 0)
     {
       queryResult_btnName = properties["btnName"].Value;
     }
      else
         {
           queryResult_btnName = String.Empty;
         }
      //get info about btn text
 if (properties.Cast<DocumentProperty>().Where(c => c.Name == "issue_title").Count() > 0)
 {
   queryResult_btnText = properties["btnText"].Value;
 }
   else
   {
     queryResult_btnText = String.Empty;
   }

 Document vstoDocument = Globals.Factory.GetVstoObject(this.Application.ActiveDocument);
 Word.Range rng = vstoDocument.Range(queryResult_StartPosition, queryResult_EndPosition); 
 Word.Selection selection = this.Application.Selection;
 if (selection != null && rng != null)
 {
   Button button = new Button();
   button.Click += new EventHandler(Generatedbtn_Click);
   button = vstoDocument.Controls.AddButton(rng, 100, 30, queryResult_btnName);
   button.Text = queryResult_btnText;
 }
}//end of wb.Documents
 
}//end of ThisAddIn_Startup

上面的代码应该能够从您创建的自定义 属性 中获取所有信息并重新创建按钮。 如果由于某种原因,当您启动文档时 adds-in 选项卡没有出现在 word 中,这意味着您的 ThisAddIn_Startup 函数有错误 - 要调试,请尝试将 ThisAddIn_Startup 函数中的所有内容放入单独的按钮中,然后进行测试并查看错误代码。 请注意:您基本上可以完成在普通 C# 表单中所做的一切(打开表单关闭表单、读取文本文件等)

我在 github 中提供了一个示例,其中包含一个您可以查看的调试按钮

Persist Dynamic Control