2016-12-22 138 views
1

我正在爲Visual Studio 2015編寫一個擴展。 我添加了一個VSPackage來將一些CustomCommands嵌入到您在解決方案資源管理器中右鍵單擊項目或文件夾時獲得的快捷菜單上。VisualStudio VSPackage自定義命令

我現在想要做的是「打開添加新項目對話框,並選擇我用這個VSPackage安裝的模板之一」。

這是我使用初始化我的命令代碼:(目前我只需創建一個消息框,只是爲了確保它的工作原理)

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); 
} 

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); 
} 

的CreateCustomTemplate回調代碼是這樣的

因此,回顧一下,如何打開添加新項目對話框並選擇特定項目模板

舉個例子,當您嘗試在Solution Explorer RightClick on Folder, then Add -> UserControl

您獲得類似這樣的東西來創建一個文件夾上一個類或用戶控件右擊: Result

這是,正是我想要達到的目標。很顯然,我想創建自己的模板而不是UserControl。

如果您需要任何澄清隨時問。 預先感謝您的任何建議

回答

0

最後我解決了我的問題。

不幸的是,命令File.AddNewItem(或Project.AddNewItem)不適合我的情況,因爲我想查看AddNewFile對話框(並且這些命令只是將項目添加到指定的項目中)。

我發現解決方案挖網,確切地說是here,特別感謝Vladimir.Ilic的回答。

這是我使用來實現我的目標代碼:

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."); 
    } 
} 

非常感謝那個路過的那些和那些試圖(甚至鑫卡特)幫助!

希望這可以幫助別人,

真誠

0

您可以執行命令「Project.AddNewItem」或「File.AddNewItem」來顯示對話框。有幾種編程方式來執行命令,最簡單的方法是獲取EnvDTE.DTE實例並調用dte.ExecuteCommand(commandName)。

至於選擇所需的模板,請參閱parameters for the command File.AddNewItem。有些運氣對於Project.AddNewItem命令是一樣的。

+0

我沒有給AddNewItem一試,因爲我認爲這將只是一個文件添加到我需要的項目。只要我能試一試,我會讓你如果和我如何解決它 – Easly