I have been developing a Visual Studio extension as an Add-in for VS2008/2010. The new version now is to be done as a VSIX package for VS2010 only (as it has to be .NET 4 anyway), and I am having some troubles with (rather simple, I would think) UI handling.
The extension primarily consists of a toolbar with some buttons that launch various actions, forms etc., and a few that are only used as labels to display some state information. The "label" buttons themselves just show very short and concise information, while the tooltips provide more detail.
While I didn't think the whole Add-in thing was very elegant, doing this kind of stuff was pretty straightforward (though my approach may have been a little amateurish). When adding the commands to the toolbar, I would "save" the "label" buttons in specific local variables, allowing me to later set the caption and tooltip text at will.
In a VSPackage, the equivalent to Microsoft.VisualStudio.CommandBars.CommandBarButton appears to be OleMenuCommand. Finding the "label" command through the MenuCommandService is no problem, modifying it as needed is, however.
For the purpose of finding out how to do this, I just have a toolbar with two buttons in a group. btnAction is very simple; just an icon and an execute handler to change the text on the other button, no CommandFlags. btnLabel looks like this in the .vsct:
<Button guid="guidVSPackageBuilderTutorialCommandSet" id="btnLabel" priority="0x0100">
<CommandFlag>DefaultDisabled</CommandFlag>
<CommandFlag>DontCache</CommandFlag>
<CommandFlag>NoCustomize</CommandFlag>
<CommandFlag>TextChanges</CommandFlag>
<CommandFlag>TextOnly</CommandFlag>
<Strings>
<CommandName>cmdidbtnLabel</CommandName>
<ButtonText>btnLabel</ButtonText>
<MenuText>btnLabel</MenuText>
<ToolTipText>Tooltip btnLabel</ToolTipText>
</Strings>
</Button>
The first problem with this is that when I use TextChanges, the ToolTipText string is ignored and the ButtonText is initially used for the tooltip as well.
The handler code for the action button is as follows:
private int iClickCount = 0;
protected override void btnActionExecuteHandler(object sender, EventArgs e)
{
var svc = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
CommandID idBtnLabel = new CommandID(GuidList.guidVSPackageBuilderTutorialCmdSet, (int)PkgCmdIDList.btnLabel);
var cmd = svc.FindCommand(idBtnLabel) as OleMenuCommand;
cmd.Text = "Clicked " + (++iClickCount) + " times";
}
This changes the caption of btnLabel as expected, but as there is no way of explicitly specifying the tooltip (the OleMenuCommand object just has a Text property, unlike CommandBarButton, which has both Caption and TooltipText), the tooltip is always set to the same string as the caption. From what I understand, this is because with FindCommand() I am not actually getting the UI button, but only the underlying command, which doesn't care about tooltips.
What's even more confusing is what happens when I use the TextChangesButton CommandFlag instead of TextChanges. The button will now correctly display the tooltip text defined in the .vsct, but neither the caption nor the tooltip will change when I click the other button - though when I check the btnLabel command's Text property, it is set to what I expect ("Clicked x times"). Does TextChangesButton kind of "decouple" the properties of the command and the button ? If so, this is pretty much what I want (I don't care about the command, as there is nothing to execute anyway; btnLabel will always be disabled), but how can I access the button and its particular string properties ?
I looked through the various IVs interfaces and SVs services but couldn't find something appropriate, and the documentation (and IntelliSense help) doesn't seem to be very extensive.