Is there a workaround or alternative to IRibbonControl.Context to access the correct window and workbook in Excel 2016 or newer?

Viewed 280

There are existing posts on SO about related topics, and there are support requests on MSDN that are unsolved/unrepaired. It sounds like the "right way" doesn't work, so I'm wondering there is a workaround.

Let me describe what I perceive to be "the right way" that doesn't work, and maybe you have an alternative path that will work.

I can create an Excel VSTO plugin in Visual Studio, create a custom Ribbon.xml and Ribbon.cs file, and then open multiple workbooks which appear as different windows. Per other SO posts, I can hook into the Application_WindowActivate event and call Invalidate() on my ribbon, forcing a refresh of all the callbacks. The ribbon will reflect the state of the Active Window... and so will every other instance of the ribbon in other windows. As a result, the Ribbon that appears in every window is the same Ribbon. If I have a CheckBox or a Button with a Pressed attribute or anything else stateful, those states will propagate to every open Excel window.

This can be avoided by running Excel with the excel /s parameter which appears to create a new process with its own SDI - but this is not a user-friendly solution.

It looks like what you're supposed to be able to do during an onAction ribbon callback is access the IRibbonControl parameter's Context property, which is supposed to be the correct Excel.Window object. In theory this would present either only the Window you are activating, or would execute for each open Window. And with the correct Context you could execute functions that provide different states back to the Ribbon. And then maybe in one Excel window, you ribbon could have a Pressed Button, and in the other window, an unpressed Button. Except it doesn't work.

When I call Invalidate I get two callbacks (not sure why, the MSDN says it might be a bug) both for the newly activated window, and I execute logic to update the state of active window's ribbon. And then the previous window's ribbon updates the same way.

If this is the way it is, fine. We'll tell our users that they may see some funky Ribbon changes on inactive windows but that it will always be correct on the active window. We can deal with that. But if there is a way around this problem that could make it appear as though the Ribbon had different states on a per-workbook/window basis... that'd be really cool.

1 Answers

You are on the right avenue. Only the active window gets callbacks invoked and its values refreshed. You must switch to another Excel window if you want your ribbon UI invalidated. For each of the callbacks the add-in implements, the responses are cached. For example, if an add-in writer implements the getImage callback procedure for a button, the function is called once, the image loads, and then if the image needs to be updated, the cached image is used instead of recalling the procedure. This process remains in-place until the add-in signals that the cached values are invalid by using the Invalidate method, at which time, the callback procedure is again called and the return response is cached. The add-in can then force an immediate update of the UI by calling the Refresh method.

You may also consider caching UI settings in custom properties. And as soon as a custom property is changed you may trigger UI updates.

Read more about the Fluent UI in the following series of articles:

Also, you may find the folliwing links helpful:

Related