Visual Studio Extensions: Adding element to the Code Editor ContextMenu - c#

I'm trying to add a new element to the Visual Studio 2017 Context Menu. I managed to add an element to the TOOLS menu with the following code:
<Button guid="guidRandomCommandPackageCmdSet" id="RandomCommandId" priority="0x0100" type="Button">
<Parent guid="guidSHLMainMenu" id="IDG_VS_TOOLS_EXT_TOOLS" />
<Icon guid="exclamationIcon" id="exclamationIcon1" />
<Strings>
<ButtonText>Random Text</ButtonText>
</Strings>
</Button>
which is registered in
<GuidSymbol name="guidRandomCommandPackageCmdSet" value="{47122772-c66f-48f3-b10b-dbbb66da120d}">
.
.
<IDSymbol name="RandomCommandId" value="0x0100" />
</GuidSymbol>
I tried to follow a similar fashion, so I defined a new Button in Buttons:
<Button guid="guidRandomCommandPackageCmdSet" id="ToDoList" priority="0x0100" type="Button">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_CODEWIN"/>
<Icon guid="exclamationIcon" id="exclamationIcon1" />
<Strings>
<ButtonText>Add TODO list</ButtonText>
</Strings>
</Button>with the ID symbol
with the ID registerd in GuidSymbols
<IDSymbol name="ToDoList" value="0x106" />
But the button does not show up in the context menu, when I run the project. I tried to follow the suggestions of VSIX: Adding a Menu Item to the Visual Studio Editor Context Menu but none of the suggestions seems to work for me.
I never tried to create a VS add-on before, so I welcome any suggestions. Is it possible that the method changed in VS 2017?

Eventually, I managed to get it working. It seems that while for MENU items that show up either as a separate menu or belonging to a menu like TOOLS, it is enough to have only a Button with the parent set to the appropriate constant menu element string as defined at GUIDs and IDs of Visual Studio Menus.
For ContextMenu elements, however, I needed to have an element in Groups:
<Group guid="guidRandomCommandPackageCmdSet" id="MyMenuGroup" priority="0x0600">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_CODEWIN" />
</Group>
This has the ContextMenu as its Parent. Then, I created a CustomCommand that auto-generates a Button with it and I modified this Button to have the Group element as itsParent:
`
Add TODO list
This is the result with the added button hovered over:

Related

Outlook VSTO - moving my group next to "New Mail" group

I have made an addin (New Flux Ad Mail) for Outlook and would like to move it's position next to the "New" group - see picture.
Currently, I have this in my xml:
<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
<ribbon startFromScratch="false">
<tabs>
<tab idMso="TabMail">
<group id="fluxAdMail" label="Flux Ad Mail">
<button id="btnNewFluxMail" label="New Flux Ad Mail" onAction="click" size="large" imageMso="NewMail"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
I noticed that there's something in the <group> section called insertAfterMso and I'm wondering if that's what I need to use set the position of my group. However, I have a hard time finding any information regarding this or what the different name/id is for the controls
Any help would be appreciated
You are on the right avenue - the insertAfterMso attribute specifies the identifier for the built-in control after which to position this control. You can can find the list of built-in control IDs at https://github.com/OfficeDev/office-fluent-ui-command-identifiers . Use the GroupMailNew idMso value for the insertAfterMso attribute in case of Explorer windows.
If you only need to find control names, you can discover them within Office applications by hovering over commands in the Customize Ribbon tab of the Options dialog and looking at the tooltip:

Xamarin.Forms Shell navigation outside the visual hierarchy

I'm having a problem with how to implement navigation to pages that are not represented in shell visual hierarchy (defined in my Shell xaml).
From what I read about Shell navigation in the docs, there are two ways I can navigate to such a page:
Using the Navigation property:
Navigation.PushAsync(new TargetPage());
Registering a route and using Shell's URI navigation:
Routing.RegisterRoute("targetPageRoute", typeof(TargetPage));
Shell.Current.GoToAsync("targetPageRoute");
Both methods encounter the same problem: Once you use either method to navigate to a page outside the visual hierarchy, normal navigation between Shell's flyoutItems (using the flyout menu) will crash the app with the error:
System.Collections.Generic.KeyNotFoundException: The given key 'MyProject.TargetPage' was not present in the dictionary.
How to reproduce:
Add two items to Shell's visual hierarchy:
<FlyoutItem Title="page 1">
<Tab>
<ShellContent>
<local:Page1 />
</ShellContent>
</Tab>
</FlyoutItem>
<FlyoutItem Title="page 2">
<Tab>
<ShellContent>
<local:Page2 />
</ShellContent>
</Tab>
</FlyoutItem>
Use a button on Page1 to navigate to Page3 (a page not defined above) using either of the two ways to navigate described at the top of this post:
private void Button_Clicked(object sender, EventArgs e) {
Navigation.PushAsync(new Page3());
}
Use the flyout menu to navigate to Page2
Use the flyout menu to navigate to Page1 - the app should now crash.
I have tested this in my main project and in a small test project extensively and cant seem to find a solution. Any help would be greatly appreciated.
Here's the same issue from xamarin forms' github: https://github.com/xamarin/Xamarin.Forms/issues/6738
Also, if you scroll down, you'll see pull request, which actually resolves the problem (already helped our company's application).
You have to implement a custom renderer, which is going to inherit from ShellItemRenderer, and override the existing HandleFragmentUpdate (because of the fact, that it uses private fields from the original ShellItemRendererBase, you'll have to rebase them here too (not override, just copy them from current xamarin android ShellItemRendererBase.cs file)).
BUT, as the official docs suggest, you shall not just assign this renderer to a ShellItem derivative, instead, you'll have to create custom ShellRenderer with overriding it's CreateShellItemRenderer method (so it would create your fixed shell item renderer instead of the default one). You just apply this renderer to a custom shell control in xamarin forms.
Of course, everything you do now is temporary, until xamarin pushes new update with this fix included...
you could try to change the shell.xaml like this:
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
<Tab Title="page 1">
<ShellContent >
<local:Page1 />
</ShellContent>
</Tab>
<Tab Title="page 2">
<ShellContent >
<local:Page2 />
</ShellContent>
</Tab>
</FlyoutItem>
Have you tried to add your Route before setting the BindingContext ?
For Example :
public NavigationShell()
{
Routing.RegisterRoute("targetPageRoute", typeof(TargetPage));
BindingContext = this;
}

Outlook - Only first "getVisible" called for contextMenu

Using this Outlook 2013, I develop an addin in C#. My ribbon.xml looks like:
<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
<contextMenus>
<!-- Move mail to -->
<contextMenu idMso="ContextMenuMailItem">
<button id="MoveMailTo_CM"
imageMso="CopyToFolder"
insertBeforeMso="Copy"
getLabel="MoveMailTo_GetLabel"
getVisible="MoveMailTo_GetVisible"
onAction="MoveMailTo_OnAction"/>
</contextMenu>
<!-- Manage holiday request -->
<contextMenu idMso="ContextMenuMailItem">
<button id="ManageHolidayRequest_CM"
imageMso="CopyToPersonalCalendar"
insertBeforeMso="Copy"
label="Copy to Calendar"
getVisible="ManageHolidayRequest_GetVisible"
onAction="ManageHolidayRequest_OnAction" />
</contextMenu>
</contextMenus>
</customUI>
When I launch my addin using Visual Studio and I right-click on an email item, only the first "getVisible" is called (the MoveMailTo_GetVisible) but not the other one.
If i switch both menu, only ManageHolidayRequest_GetVisible is called.
Can't we specify two different function in that case? Any workaround ?
Best regards,
Answer was : I had two <contextMenu idMso="ContextMenuMailItem"> (so for the same Mso). Just merged both button in context Menu and worked.

How get ID of TeamExplorer Builds

I make Hello world of VSIX extension.
I created VSIX Project and added Custom Command.
I want add this control to Team Explorer -> Build.
In TFSTreeViewPackage.vsct I have:
<Groups>
<Group guid="guidTFSTreeViewPackageCmdSet" id="MyMenuGroup" priority="0x0600">
<Parent guid="guidSHLMainMenu" id="IDM_VS_MENU_TOOLS"/>
</Group>
</Groups>
What id I should put, after where my control will place in build windows?
You can use this extension to find where existing commands are placed.
For example, how to find where Team Explorer -> Build -> Build Definition -> Add to favorite.
Use the inspect mode to find the command. once you find it, copy the guid and the id of the containing item:
If the guid synmbol and the id symbol not found, you will need to add them:
<GuidSymbol name="guidBigBuildCmdSet" value="{34586048-8400-472e-bbbf-3ae30af8046e}">
<IDSymbol name="menuBuildsPageDefinition" value="0x109" />
</GuidSymbol>
And change your group to:
<Groups>
<Group guid="guidTFSTreeViewPackageCmdSet" id="MyMenuGroup" priority="0x0600">
<Parent guid="guidBigBuildCmdSet" id="menuBuildsPageDefinition"/>
</Group>
</Groups>

KeyTip not working in Microsoft Ribbon

The 'KeyTip' is not working properly using the RibbonControlsLibrary (3.5.41019.1). I create a simple RibbonWindow:
Add a couple of tabs
Add some controls like a button
Set properties such as labels and headers
Set the KeyTip properties on the tabs
I test the KeyTip in desgin mode (VS2010) and everything works as expected. But when I build the project as a windows application the following occur:
ALT+KeyTip only shows the keytips, no focus is changing. The expected behaviour would be a change of tab...
I tried to create a clean WpfRibbonProject and did the same thing and then it works for some reason. The none working project is a mixture of Forms and WPF and a form is displayed before the WPF window. Could this be the problem? I cannon see why this would be a problem?
Source code:
<ribbon:RibbonTab x:Name="HomeTab"
Header="Home" KeyTip="H">
<ribbon:RibbonGroup x:Name="Group1"
Header="Group1">
<ribbon:RibbonButton Label="Hej" KeyTip="T" />
</ribbon:RibbonGroup>
</ribbon:RibbonTab>
<ribbon:RibbonTab Header="Tab1">
<ribbon:RibbonGroup Header="Min grupp">
<ribbon:RibbonButton Label="Test" />
<ribbon:RibbonSplitButton Label="Testen">
<ribbon:RibbonMenuItem Header="Jaha" />
</ribbon:RibbonSplitButton>
</ribbon:RibbonGroup>
</ribbon:RibbonTab>
<ribbon:RibbonTab Header="Tab2" KeyTip="2" />
<ribbon:RibbonTab Header="Tab3" KeyTip="3" />
</ribbon:Ribbon>
I managed to fix the problem by adding the following line of code before i show the WPF Window:
System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(this);
This is necessary if you mix WinForms and WPF windows in the same project at least if the WinForm is shown before the WPF window.
In Ribbon cotrol add property: KeyboardNavigation.ControlTabNavigation
<ribbon:Ribbon DockPanel.Dock="Top" SelectedIndex="1" KeyboardNavigation.ControlTabNavigation="Contained">
It's working for me.

Categories