如何在ThisAddIn.cs触发事件时修改Ribbon XML的getVisible属性
解决Word VSTO插件运行时动态隐藏Backstage保存选项卡的问题
我开发了一个Word VSTO插件,已通过DocumentOpen、DocumentBeforePrint和DocumentBeforeSave事件实现了根据文档和用户权限限制保存、打印及修改操作,插件运行正常。现在需要在DocumentBeforeSave事件触发且用户操作被阻止时,动态隐藏Backstage中的Save选项卡(TabSave)。
尝试过切换多个Ribbon XML但仅生效一次;也尝试使用getVisible和getEnabled属性,但不知道如何在事件中触发状态更新。
现有代码如下:
ThisAddIn.cs
public partial class ThisAddIn { [DllImport("epsede.dll", CharSet = CharSet.Unicode)] public static extern int E1(int Event, IntPtr window, [MarshalAs(UnmanagedType.LPWStr)] String FileName); internal Ribbon1 Ribbon1; private void ThisAddIn_Startup(object sender, System.EventArgs e) { Globals.ThisAddIn.Application.DocumentBeforeSave += new Microsoft.Office.Interop.Word.ApplicationEvents4_DocumentBeforeSaveEventHandler(this.Application_DocumentBeforeSave); } protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject() { Ribbon1 = new Ribbon1(); return Ribbon1; } //Before Save public void Application_DocumentBeforeSave(Microsoft.Office.Interop.Word.Document Doc, ref bool SaveAsUI, ref bool Cancel) { IntPtr hWnd = Process.GetCurrentProcess().MainWindowHandle; if (E1(2, hWnd, Doc.FullName) == 0) { // 允许保存 } else { System.Windows.Forms.MessageBox.Show("Blocked Saving"); Cancel = true; // 这里需要触发隐藏Save选项卡 } } 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 }
Ribbon1.xml
<?xml version="1.0" encoding="UTF-8"?> <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load"> <backstage> <tab idMso ="TabSave" getVisible="IsTabSaveVisible" getEnabled="IsTabSaveEnabled"/> </backstage> </customUI>
Ribbon1.cs
namespace WordS { [ComVisible(true)] public class Ribbon1 : Office.IRibbonExtensibility { private Office.IRibbonUI ribbon; private bool _isSaveTabVisible = true; private bool _isSaveTabEnabled = true; // 控制Save选项卡可见性的属性 public bool IsSaveTabVisible { get => _isSaveTabVisible; set { _isSaveTabVisible = value; ribbon?.InvalidateControlMso("TabSave"); // 仅刷新指定控件,比全局Invalidate更高效 } } // 控制Save选项卡可用性的属性 public bool IsSaveTabEnabled { get => _isSaveTabEnabled; set { _isSaveTabEnabled = value; ribbon?.InvalidateControlMso("TabSave"); } } public Ribbon1() { } #region IRibbonExtensibility Members public string GetCustomUI(string ribbonID) { return GetResourceText("WordS.Ribbon1.xml"); } #endregion #region Ribbon Callbacks public void Ribbon_Load(Office.IRibbonUI ribbonUI) { this.ribbon = ribbonUI; } // getVisible回调方法,必须与XML中指定的名称一致 public bool IsTabSaveVisible(Office.IRibbonControl control) { return _isSaveTabVisible; } // getEnabled回调方法,可选,用于禁用而非隐藏 public bool IsTabSaveEnabled(Office.IRibbonControl control) { return _isSaveTabEnabled; } } }
实现步骤
完善Ribbon回调方法
- 在
Ribbon1.cs中添加与XML中getVisible、getEnabled对应的回调函数,名称必须完全匹配XML中的属性值。 - 使用
InvalidateControlMso替代全局Invalidate,只刷新目标控件(TabSave),提升性能。
- 在
在事件中更新状态
修改ThisAddIn.cs中的Application_DocumentBeforeSave方法,当阻止保存时,更新Ribbon的状态:public void Application_DocumentBeforeSave(Microsoft.Office.Interop.Word.Document Doc, ref bool SaveAsUI, ref bool Cancel) { IntPtr hWnd = Process.GetCurrentProcess().MainWindowHandle; int result = E1(2, hWnd, Doc.FullName); if (result == 0) { // 允许保存时,恢复Save选项卡的可见性和可用性 Ribbon1.IsSaveTabVisible = true; Ribbon1.IsSaveTabEnabled = true; } else { System.Windows.Forms.MessageBox.Show("Blocked Saving"); Cancel = true; // 阻止保存时,隐藏并禁用Save选项卡 Ribbon1.IsSaveTabVisible = false; Ribbon1.IsSaveTabEnabled = false; } }处理文档切换场景
若需要在打开新文档或切换文档时重新检查权限,可添加DocumentOpen和WindowActivate事件:private void ThisAddIn_Startup(object sender, System.EventArgs e) { Globals.ThisAddIn.Application.DocumentBeforeSave += Application_DocumentBeforeSave; Globals.ThisAddIn.Application.DocumentOpen += Application_DocumentOpen; Globals.ThisAddIn.Application.WindowActivate += Application_WindowActivate; } private void Application_WindowActivate(Microsoft.Office.Interop.Word.Document Doc, Microsoft.Office.Interop.Word.Window Wn) { CheckAndUpdateSaveTabPermission(Doc); } private void Application_DocumentOpen(Microsoft.Office.Interop.Word.Document Doc) { CheckAndUpdateSaveTabPermission(Doc); } private void CheckAndUpdateSaveTabPermission(Microsoft.Office.Interop.Word.Document Doc) { IntPtr hWnd = Process.GetCurrentProcess().MainWindowHandle; int result = E1(/* 传入对应检查权限的Event参数 */, hWnd, Doc.FullName); if (result == 0) { Ribbon1.IsSaveTabVisible = true; Ribbon1.IsSaveTabEnabled = true; } else { Ribbon1.IsSaveTabVisible = false; Ribbon1.IsSaveTabEnabled = false; } }
关键说明
- Ribbon控件的状态更新必须通过
Invalidate或InvalidateControlMso触发Office重新加载控件属性,直接修改变量不会生效。 - 使用
InvalidateControlMso("TabSave")比全局Invalidate()更高效,避免刷新整个Ribbon。 - 若需要同时控制多个内置控件,可多次调用
InvalidateControlMso,或使用Invalidate()刷新全部控件。
内容的提问来源于stack exchange,提问作者Maryam Ghayori
相关产品推荐
相关产品推荐

