如何在Visual Studio 2019自定义项目模板中添加多种方案选项
I get exactly what you're after—you want a single project template that presents users with a choice of sub-types (like Custom Utility, Custom UI) right after they click "Create", just like how ASP.NET lets you pick Empty, Web Forms, etc. Most tutorials fixate on multi-project templates, but this is a different scenario that uses custom template wizards to add that selection step. Here's a step-by-step breakdown to make this work:
1. Prep Your Base Project Structures
First, build out the core project files for each of your sub-options:
- Create a standalone "Custom Utility" project, clean up build artifacts (bin/obj folders, .vs cache), and save its files in a folder like
TemplateAssets/CustomUtility/ - Repeat this for "Custom UI" and "Custom Component", storing each in their own subfolders under
TemplateAssets/
2. Create the Main Template Configuration
Make a root-level .vstemplate file (name it CustomProjectTemplate.vstemplate) that defines your main template and hooks up the custom wizard. This tells Visual Studio to launch your selection dialog instead of generating files immediately:
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project"> <TemplateData> <Name>Custom Project</Name> <Description>Choose from custom utility, UI, or component project types</Description> <ProjectType>CSharp</ProjectType> <SortOrder>1000</SortOrder> <CreateNewFolder>true</CreateNewFolder> <DefaultName>CustomProject</DefaultName> <Icon>TemplateIcon.ico</Icon> </TemplateData> <TemplateContent> <Project File="Placeholder.csproj" ReplaceParameters="true"> </Project> <WizardExtension> <Assembly>CustomTemplateWizard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</Assembly> <FullClassName>CustomTemplateWizard.TemplateSelectionWizard</FullClassName> </WizardExtension> </TemplateContent> </VSTemplate>
The Placeholder.csproj is just a dummy project file—your wizard will replace it with the correct files based on user selection.
3. Build the Custom Template Wizard
This is the magic part: a .NET Framework class library that implements Visual Studio's IWizard interface to show the selection dialog and handle file filtering.
Create a new Class Library (.NET Framework 4.7.2 or higher—VS runs on this framework) and add this code:
using Microsoft.VisualStudio.TemplateWizard; using System.Collections.Generic; using System.Windows.Forms; namespace CustomTemplateWizard { public class TemplateSelectionWizard : IWizard { private string _selectedType; public void RunStarted(object automationObject, Dictionary<string, string> replacements, WizardRunKind runKind, object[] customParams) { // Launch the selection dialog using (var dialog = new TemplateChoiceDialog()) { if (dialog.ShowDialog() != DialogResult.OK) { // Cancel template creation if user closes the dialog throw new WizardCancelledException(); } _selectedType = dialog.SelectedTemplateType; // Add custom parameter for file replacement/filtering replacements.Add("$selectedTemplateType$", _selectedType); } } // Filter which files get added based on user selection public bool ShouldAddProjectItem(string filePath) { // Only include files from the selected sub-template folder return filePath.Contains(_selectedType); } // Empty implementations for required IWizard methods public void BeforeOpeningFile(EnvDTE.ProjectItem projectItem) { } public void ProjectFinishedGenerating(EnvDTE.Project project) { } public void ProjectItemFinishedGenerating(EnvDTE.ProjectItem projectItem) { } public void RunFinished() { } } // Custom dialog for template selection public class TemplateChoiceDialog : Form { public string SelectedTemplateType { get; private set; } public TemplateChoiceDialog() { Text = "Select Custom Project Type"; Size = new System.Drawing.Size(320, 180); var header = new Label { Text = "Pick your project type:", Location = new System.Drawing.Point(20, 20) }; var utilityRadio = new RadioButton { Text = "Custom Utility", Location = new System.Drawing.Point(30, 50), Tag = "CustomUtility" }; var uiRadio = new RadioButton { Text = "Custom UI", Location = new System.Drawing.Point(30, 80), Tag = "CustomUI" }; var componentRadio = new RadioButton { Text = "Custom Component", Location = new System.Drawing.Point(30, 110), Tag = "CustomComponent" }; var okBtn = new Button { Text = "OK", Location = new System.Drawing.Point(130, 140), DialogResult = DialogResult.OK }; okBtn.Click += (s, e) => { if (utilityRadio.Checked) SelectedTemplateType = (string)utilityRadio.Tag; else if (uiRadio.Checked) SelectedTemplateType = (string)uiRadio.Tag; else if (componentRadio.Checked) SelectedTemplateType = (string)componentRadio.Tag; }; Controls.Add(header); Controls.Add(utilityRadio); Controls.Add(uiRadio); Controls.Add(componentRadio); Controls.Add(okBtn); AcceptButton = okBtn; } } }
Compile this library to get CustomTemplateWizard.dll.
4. Package and Install the Template
- Gather all your assets: the main
.vstemplate,CustomTemplateWizard.dll,TemplateAssets/folder, placeholder.csproj, and your template icon. - Zip everything up (make sure the root of the zip is the template root—no nested folders inside the zip).
- Place the zip file in your Visual Studio project templates folder:
For VS 2022, this is usuallyC:\Users\<YourUsername>\Documents\Visual Studio 2022\Templates\ProjectTemplates\Visual C#
5. Test It Out
Restart Visual Studio, search for "Custom Project", go through the name/location steps, and click "Create"—your custom selection dialog should pop up. Pick an option, and VS will generate the corresponding project files.
内容的提问来源于stack exchange,提问作者Rahul Khandelwal

