通过Workbook_Open事件更改VSTO选项卡的可见属性

我已经为Excel VSTO项目编写了Ribbon.xml文件。 标签元素看起来像这样:

<tab id="myId" idMso="TabAddIns" label="My Tab" visible="false"> 

当打开一个工作簿时,我希望该选项卡被默认隐藏,这是通过将visible属性设置为false来实现的。 接下来,我想在Workbook_Open事件中将visible属性更改为true。 这是我卡住的地方。 我不认为这会很难,但是我花了几个小时的时间search答案。 看来,大多数例子1)通过buttoncallback来切换标签的可见性,这不是我想要做的,或者2)能够访问function区的属性 ,而目前为止我还没有能够复制这些属性 (尽pipe大多数这些资源是旧的,所以我认为MS从那时起就把这些属性转移了)。

有谁知道如何轻松地将可视属性更改为true,以便显示该选项卡?

谢谢!

更新了其他信息:

ThisAddIn.cs

 namespace Doodles_Reporting { public partial class ThisAddIn { public RibbonApi ribbonApi; private void ThisAddIn_Startup(object sender, System.EventArgs e) { } private void ThisAddIn_Shutdown(object sender, System.EventArgs e) { } protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject() { return new Ribbon(); } void Application_WorkbookOpen(Excel.Workbook Wb) { //first, check if there is an application/process for each workbook Excel.Workbooks books = Globals.ThisAddIn.Application.Workbooks; if (books.Count > 1) { try { //close workbook that was just opened and then reopen it with new process/application. string filePath = Wb.FullName; Wb.Close(); Excel.Application excelApp = new Excel.Application(); excelApp.Visible = true; excelApp.DisplayFullScreen = true; excelApp.Workbooks.Open(filePath); } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK); } } else { //second, check if the workbook is a Doodles workbook try { DocumentProperties props = (DocumentProperties)Wb.CustomDocumentProperties; var selectedTable = props["selectedTable"].Value; configureDoodles(); } catch (Exception) { //THIS IS WHERE I WANT TO SET THE RIBBON VISIBILITY TO FALSE } } } private void configureDoodles() { RibbonApi.app = Globals.ThisAddIn.Application; RibbonApi.wBookPropertiesConfig = new WorkbookPropertiesConfig(RibbonApi.app.ActiveWorkbook); RibbonApi.presenter = new ExcelPresenter(RibbonApi.app.ActiveWorkbook); ribbonApi = new RibbonApi(); } #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); this.Application.WorkbookOpen += new Excel.AppEvents_WorkbookOpenEventHandler(Application_WorkbookOpen); } #endregion } } 

Ribbon.cs

 namespace Doodles_Reporting { [ComVisible(true)] public class Ribbon : Office.IRibbonExtensibility { private Office.IRibbonUI ribbon; public Ribbon() { } #region IRibbonExtensibility Members public string GetCustomUI(string ribbonID) { return GetResourceText("Doodles_Reporting.Ribbon.xml"); } #endregion #region Ribbon Callbacks //Create callback methods here. For more information about adding callback methods, visit http://go.microsoft.com/fwlink/?LinkID=271226 public void Ribbon_Load(Office.IRibbonUI ribbonUI) { this.ribbon = ribbonUI; } public bool toggleVisibility(Office.IRibbonControl control) { return (control.Id == "TabAddIns") ? true : false; } public void onSomeEvent() { this.ribbon.InvalidateControl("TabAddIns"); } public void SignIn(Office.IRibbonControl ribbonUI) { Globals.ThisAddIn.ribbonApi.signIn(); } public void SqlCreatorFormLoad(Office.IRibbonControl ribbonUI) { Globals.ThisAddIn.ribbonApi.showSqlCreator(); } public void refreshData(Office.IRibbonControl ribbonUI) { Globals.ThisAddIn.ribbonApi.refreshData(); } public void drilldownSelectionLoad(Office.IRibbonControl ribbonUI) { Globals.ThisAddIn.ribbonApi.setDrilldownColumns(); } public void Drilldown(Office.IRibbonControl ribbonUI) { Globals.ThisAddIn.ribbonApi.drilldown(); } public void editProperties(Office.IRibbonControl ribbonUI) { } #endregion #region Helpers private static string GetResourceText(string resourceName) { Assembly asm = Assembly.GetExecutingAssembly(); string[] resourceNames = asm.GetManifestResourceNames(); for (int i = 0; i < resourceNames.Length; ++i) { if (string.Compare(resourceName, resourceNames[i], StringComparison.OrdinalIgnoreCase) == 0) { using (StreamReader resourceReader = new StreamReader(asm.GetManifestResourceStream(resourceNames[i]))) { if (resourceReader != null) { return resourceReader.ReadToEnd(); } } } } return null; } #endregion } } 

丝带是一个有趣的野兽。 它是专门devise的,不允许你直接访问它的任何元素,并禁止你直接操纵它们。 相反,一切都是通过callback完成的。 我对VSTO没有太多的经验,但是我可以在没有VSTO的情况下解释一下C#或者C ++中你会做什么,我相信你可以填补空白。

  1. 在function区XML中设置onLoadcallback。 当第一次加载function区时,Excel将调用此方法(通过IDispatch )。

     <customUI ... onLoad="OnRibbonLoaded"> 
  2. 实现你的onLoadcallback,它应该存储提供的IRibbonUI引用。

     public void OnRibbonLoaded(IRibbonUI ribbon) { this.ribbon = ribbon; } 
  3. 对于要dynamic控制的属性,请在function区XML中定义callback。

     <tab ... getVisible="GetVisible"> 
  4. 实现您的可见性callback。 如果function区的多个部分使用相同的callback,则传递到此方法的IRibbonControl实例可用于确定要查询哪个选项卡/组/控制。

     public bool GetVisible(IRibbonControl control) { // here is where you should determine if your tab/group/control should be visible, return (some condition) ? true : false; } 
  5. 无论何时您决定要更新可视性,请通过使用IRibbonUI引用,让Excel重新查询您的控件的属性(即调用您的callback)。

     void OnSomeEvent() { // you can tell Excel to update the entire ribbon this.ribbon.Invalidate(); // or you can tell Excel to update a single tab/group/control this.ribbon.InvalidateControl("my_id"); } 

你已经得到了所有的东西。

ThisAddin ,您重写了CreateRibbonExtensibilityObject 。 而不是返回一个new Ribbon ,返回你保持的对象。

 public partial class ThisAddIn { private readonly Ribbon _ribbon = new Ribbon(); protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject() { return this._ribbon; } } 

然后,为该对象添加一个公共的Invalidate()方法,或者将该对象的IRibbonUI字段公开并调用Invalidate / InvalidateControl 。 我可能会做前者。

 [ComVisible(true)] public class Ribbon : Office.IRibbonExtensibility { private Office.IRibbonUI _ribbonUI; public void Invalidate() { this._ribbonUI.Invalidate(); } public void InvalidatePlayButton() { this._ribbonUI.Invalidate("PlayButton"); } } 

然后从Application_WorkbookOpen调用这些公共方法。

 public partial class ThisAddIn { void Application_WorkbookOpen(Excel.Workbook Wb) { this._ribbon.Invalidate(); this._ribbon.InvalidatePlayButton(); } } 

请注意,如果喜欢,可以将这些对象组合成一个对象。 只要让ThisAddin实现Microsoft.Office.Core.IRibbonExtensibility并从CreateRibbonExtensibilityObject返回。

但是,创build一个单独的对象有一些优点。 例如,将function区封装在更健壮的公共方法和属性中变得很容易。 例如:

 public class Ribbon : Office.IRibbonExtensibility { private Office.IRibbonUI _ribbonUI; private bool _isPlayButtonVisible = true; // here's a property that makes it easy to update the visibility of the play button public bool IsPlayButtonVisible { get { return this._isPlayButtonVisible; } set { if (this._isPlayButtonVisible != value) { this._isPlayButtonVisible = value; this._ribbonUI.InvalidateControl("PlayButton"); } } } // here's the callback that Excel will call public bool GetIsPlayButtonVisible(IRibbonControl control) { return this.IsPlayButtonVisible } } 

所以,我发现使用function区devise器使得这个更简单。 在创build新的Ribbon Designer类之后,该类将被添加到Globals.Ribbons下的对象模型中。 所有这一切意味着隐藏选项卡变得像我认为应该与一行代码一样简单:

 Globals.Ribbons.RibbonVisual.Doodles.Visible = false; 

RibbonVisual是我创build的Ribbon Designer类的名称, Doodles是选项卡的名称。

从现在开始,我将使用Ribbondevise师lol:P。