I'm writing a little extension for Visual Studio 2015. I added a VSPackage to to embed some CustomCommands on the Shortcut Menu you get when you RightClick on a Project or a Folder inside the Solution Explorer.
What I would like to do now is "open the Add New Item dialog and select the one of the templates I've installed with this VSPackage".
This is the Code I use to initialize my commands:
private TemplateCommand(Package package)
{
if (package == null)
throw new ArgumentNullException(nameof(package));
_package = package;
var commandService = ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (commandService == null)
return;
AddCommand(commandService, CommandId, CreateCustomTemplate);
}
The CreateCustomTemplate callback code is this:(for the moment I simply create a messageBox, just to ensure it works)
private void CreateCustomTemplate(object sender, EventArgs eventArgs)
{
//TODO: code to replace!
var message = string.Format(CultureInfo.CurrentCulture, "Inside {0}.CreateCustomTemplate()", GetType().FullName);
// Show a message box to prove we were here
VsShellUtilities.ShowMessageBox(
ServiceProvider,
message,
"CREATE CustomTemplate",
OLEMSGICON.OLEMSGICON_INFO,
OLEMSGBUTTON.OLEMSGBUTTON_OK,
OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
}
So, to recap, how do I open the Add New Item dialog box and select a specific item template?
As an example, when you try to create a Class or a UserControl right-clicking on a folder in the solution explorer
You obtain something similar to this:
And this is, exactly, what I'm trying to achieve. Obviously I would like to create my own template and not the UserControl.
If you need any clarification feel free to ask. Thank you in advance for any suggestion
In the end I resolved my problem.
Unfortunately the command File.AddNewItem (or Project.AddNewItem) is not suitable in my case as I want to see the AddNewFile Dialog (and these command simply adds the item to the specified project).
I Found the solution digging the web, exactly here, specifically thanks to the answer of Vladimir.Ilic.
This is the code I use to achieve my goal:
internal sealed class TemplateCommand
{
private const int CustomCommandId = 0x1023;
private static readonly Guid CommandSet = COMMANDSET_GUID;
private readonly Package _package;
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedAutoPropertyAccessor.Global
public IServiceProvider ServiceProvider => _package;
public static TemplateCommand Instance { get; set; }
// ReSharper restore UnusedAutoPropertyAccessor.Global
// ReSharper restore MemberCanBePrivate.Global
public static void Initialize(Package package)
{
Instance = new TemplateCommand(package);
}
private TemplateCommand(Package package)
{
if (package == null)
throw new ArgumentNullException(nameof(package));
_package = package;
var commandService = ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (commandService == null)
return;
AddCommand(commandService, CustomCommandId, CreateCustomCommand);
}
private static void AddCommand(IMenuCommandService commandService, int commandId, EventHandler callback)
{
var command = new CommandID(CommandSet, commandId);
var menuItem = new MenuCommand(callback, command);
commandService.AddCommand(menuItem);
}
private void CreateCustomCommand(object sender, EventArgs eventArgs)
{
AddNewItem("MyCustomCommand");
}
private void AddNewItem(string itemName)
{
var dte = ServiceProvider.GetService(typeof(DTE)) as DTE;
if (dte == null)
return;
int iDontShowAgain;
uint projectItemId;
var strFilter = string.Empty;
var hierarchy = GetCurrentVsHierarchySelection(out projectItemId);
if (hierarchy == null)
return;
var project = ToDteProject(hierarchy);
if (project == null)
return;
var vsProject = ToVsProject(project);
if (vsProject == null)
return;
var addItemDialog = ServiceProvider.GetService(typeof(IVsAddProjectItemDlg)) as IVsAddProjectItemDlg;
if (addItemDialog == null)
return;
const uint uiFlags = (uint)(__VSADDITEMFLAGS.VSADDITEM_AddNewItems | __VSADDITEMFLAGS.VSADDITEM_SuggestTemplateName | __VSADDITEMFLAGS.VSADDITEM_AllowHiddenTreeView);
const string categoryNameInNewFileDialog = "MyCustomTemplates";
// ProjectGuid for C# projects
var projGuid = new Guid("FAE04EC0-301F-11D3-BF4B-00C04F79EFBC");
string projectDirectoryPath;
hierarchy.GetCanonicalName(projectItemId, out projectDirectoryPath);
var itemNameInNewFileDialog = itemName;
addItemDialog.AddProjectItemDlg(projectItemId,
ref projGuid,
vsProject,
uiFlags,
categoryNameInNewFileDialog,
itemNameInNewFileDialog,
ref projectDirectoryPath,
ref strFilter,
out iDontShowAgain);
}
private static IVsHierarchy GetCurrentVsHierarchySelection(out uint projectItemId)
{
IntPtr hierarchyPtr, selectionContainerPtr;
IVsMultiItemSelect mis;
var monitorSelection = (IVsMonitorSelection)Package.GetGlobalService(typeof(SVsShellMonitorSelection));
monitorSelection.GetCurrentSelection(out hierarchyPtr, out projectItemId, out mis, out selectionContainerPtr);
var hierarchy = Marshal.GetTypedObjectForIUnknown(hierarchyPtr, typeof(IVsHierarchy)) as IVsHierarchy;
return hierarchy;
}
private static Project ToDteProject(IVsHierarchy hierarchy)
{
if (hierarchy == null)
throw new ArgumentNullException(nameof(hierarchy));
object prjObject;
if (hierarchy.GetProperty(0xfffffffe, (int)__VSHPROPID.VSHPROPID_ExtObject, out prjObject) == VSConstants.S_OK)
return (Project)prjObject;
throw new ArgumentException("Hierarchy is not a project.");
}
private IVsProject ToVsProject(Project project)
{
if (project == null)
throw new ArgumentNullException(nameof(project));
var vsSln = ServiceProvider.GetService(typeof(IVsSolution)) as IVsSolution;
if (vsSln == null)
throw new ArgumentException("Project is not a VS project.");
IVsHierarchy vsHierarchy;
vsSln.GetProjectOfUniqueName(project.UniqueName, out vsHierarchy);
// ReSharper disable SuspiciousTypeConversion.Global
var vsProject = vsHierarchy as IVsProject;
// ReSharper restore SuspiciousTypeConversion.Global
if (vsProject != null)
return vsProject;
throw new ArgumentException("Project is not a VS project.");
}
}
Big thanks to the ones that passed by and that have tried (or even thinked) to help!
Hope this helps someone,
Sincerely