Reputation: 1146
I am finding myself repeating a lot of XML when writing RibbonXML UIs.
Take, for example, the following contextMenu
<contextMenu idMso="ContextMenuObjectsGroup">
<!-- Lots of XML describing the items -->
</contextMenu>
Now, I also want the same items to appear in the ContextMenuShape
menu, so I find myself duplicating the above:
<contextMenu idMso="ContextMenuShape">
<!-- Lots of XML describing the items -->
</contextMenu>
This is exacerbated by the fact that all contained controls need new Id
s - and the code behind needs to be adapted to respond to these new controls.
Is there a way to de-duplicate this code and simply reference control groups (which are implemented once) from within, e.g.,
contextMenu
s,ribbon
s and so on?
I developed a couple of custom user functions which can be applied to shapes, tables, charts and so on. I am currently including these tools in the tab set TabSetDrawingTools
. However, I also need them included in the respective tabs for tables and charts.
From what I see right now, there are only two options:
As above, completely copy & paste all the code - which is contrary to any sort of best practices
Somehow implement my "own" ribbon XML tags. I then read my own XML, look for tags such as <customControlGroup id="myId" />
and then, from that, generate the final Ribbon XML programmatically and pass it to Office. That said, this sounds like a lot of hassle to achieve something seemingly so simple.
<control />
Not SupportedRibbon XML offers the <control />
tag, allowing you to duplicate/clone built-in controls. However, as per the documentation (and having tried it), it does not work with custom controls and control groups (e.g. by referencing their id
or idQ
).
Upvotes: 1
Views: 255
Reputation: 3529
While I am not quite a VSTO expert, I have made plentiful use of Ribbon XML, and I think what you're trying to accomplish cannot be done through Ribbon XML. But based on one of your comments, I think you may be missing part of the puzzle which will make this easier.
Use common callbacks and tag
Your code should adapt to the selection, not the controls (you need to do this anyway for error checking), and you can use the same callback across multiple controls. If you need to make a further distinction, you can also use the tag
attribute. Only the id
would be different, but it can be ignored, and your code can behave the same each time.
<contextMenu idMso="ContextMenuObjectsGroup">
<control id="mycustomcontrol1" onAction="PerformChange" tag="type1" ?>
</contextMenu>
<contextMenu idMso="ContextMenuShape">
<control id="mycustomcontrol2" onAction="PerformChange" tag="type2" ?>
</contextMenu>
public void PerformChange(IRibbonControl control)
{
bool type1 = controlTag == "Type1";
bool type2 = controlTag == "Type2";
if (/* selection contains appropriate content */)
{
// perform changes, checking the tag as needed
}
}
Use XSLT
This is mostly an addition to the previous section, to prevent having to manually copy/paste each group of controls.
Most people won't need to write or edit Ribbon XML all that often. You typically do it once and then make occasional changes. If you really need to write/edit Ribbon XML all that often, you could maintain a base copy of your Ribbon XML that contains empty <contextMenu>
's, and when you make changes, run a transform which places a copy of your elements into each relevant <contextMenu>
, with a unique id (that is, again, otherwise ignored).
I personally find that those things can be hard to get just right though unless you do it on a regular basis. If you're not super familiar with XSLT, or are not making frequent (daily? weekly?) changes to your ribbon, I doubt any time spent would be recouped through its use.
Upvotes: 1