Share via


Walkthrough: Creating a Custom Action Project Item with an Item Template, Part 2

After you define a custom type of SharePoint project item and associate it with an item template in Visual Studio, you might also want to provide a wizard for the template. You can use the wizard to collect information from users when they use your template to add a new instance of the project item to a project. The information that you collect can be used to initialize the project item.

In this walkthrough, you will add a wizard to the Custom Action project item that is demonstrated in Walkthrough: Creating a Custom Action Project Item with an Item Template, Part 1. When a user adds a Custom Action project item to a SharePoint project, the wizard collects information about the custom action (such as its location and the URL to navigate to when it is clicked) and adds this information to the Elements.xml file in the new project item.

This walkthrough demonstrates the following tasks:

  • Creating a wizard for a custom SharePoint project item type that is associated with an item template.

  • Defining a custom wizard UI that resembles the built-in wizards for SharePoint project items in Visual Studio 2010.

  • Using replaceable parameters to initialize SharePoint project files with data that you collect in the wizard.

  • Debugging and testing the wizard.

Note

You can download a sample that contains the completed projects, code, and other files for this walkthrough from the following location: https://go.microsoft.com/fwlink/?LinkId=191369.

Prerequisites

To perform this walkthrough, you must first create the CustomActionProjectItem solution by completing Walkthrough: Creating a Custom Action Project Item with an Item Template, Part 1.

You also need the following components on the development computer to complete this walkthrough:

Knowledge of the following concepts is helpful, but not required, to complete the walkthrough:

Creating the Wizard Project

To complete this walkthrough, you need to add a new project to the CustomActionProjectItem solution that you created in Walkthrough: Creating a Custom Action Project Item with an Item Template, Part 1. You will implement the IWizard interface and define the wizard UI in this project.

To create the wizard project

  1. Open the CustomActionProjectItem solution in Visual Studio.

  2. In Solution Explorer, right-click the solution node, click Add, and then click New Project.

    Note

    In Visual Basic projects, the solution node appears in Solution Explorer only when the Always show solution check box is selected in the General, Projects and Solutions, Options Dialog Box.

  3. In the New Project dialog box, expand the Visual C# or Visual Basic nodes, and then click the Windows node.

  4. In the combo box at the top of the New Project dialog box, make sure that .NET Framework 4 is selected.

  5. Select the WPF User Control Library project template.

  6. In the Name box, type ItemTemplateWizard.

  7. Click OK.

    Visual Studio adds the ItemTemplateWizard project to the solution.

  8. Delete the UserControl1 item from the project.

Configuring the Wizard Project

Before you create the wizard, you have to add a WPF window, code file, and assembly references to the project.

To configure the wizard project

  1. In Solution Explorer, right-click the ItemTemplateWizard project node and then click Properties.

  2. In the Project Designer, change the target framework from the .NET Framework 4 Client Profile to the .NET Framework 4. In Visual C# projects, you can do this on the Application tab; for Visual Basic projects, you can do this on the Compile tab. For more information, see How to: Target a Specific .NET Framework Version or Profile.

    Note

    By default, when you create a new project that targets the .NET Framework 4, the project targets the client profile. This walkthrough requires the full .NET Framework 4.

  3. In the ItemTemplateWizard project, add a new Window (WPF) item to the project. Name the new item WizardWindow.

  4. Add two code files with the following names:

    • CustomActionWizard

    • Strings

  5. On the Project menu, click Add Reference.

  6. On the .NET tab, press CTRL and click the following assemblies, and then click OK:

    • EnvDTE

    • Microsoft.VisualStudio.Shell.10.0

    • Microsoft.VisualStudio.TemplateWizardInterface

  7. In Solution Explorer, under the References folder for the ItemTemplateWizard project, click EnvDTE.

    Note

    In Visual Basic projects, the References folder appears only when the Always show solution check box is selected in the General, Projects and Solutions, Options Dialog Box.

  8. In the Properties window, change the Embed Interop Types property to False.

Defining the Default Location and ID Strings for Custom Actions

Every custom action has a location and ID that is specified in the GroupID and Location attributes of the CustomAction element in the Elements.xml file. In this step, you define some of the valid strings for these attributes in the ItemTemplateWizard project. When you complete this walkthrough, these strings are written to the Elements.xml file in the Custom Action project item when users select a location and ID in the wizard.

For simplicity, this sample supports only a subset of the available default locations and IDs. For a full list, see Default Custom Action Locations and IDs.

To define the default location and ID strings

  1. In the ItemTemplateWizard project, open the Strings code file.

  2. Replace the code in this file with the following code.

    ' This sample only supports several custom action locations and their group IDs. 
    Friend Class CustomActionLocations
        Friend Const ListEdit As String = "Microsoft.SharePoint.ListEdit"
        Friend Const StandardMenu As String = "Microsoft.SharePoint.StandardMenu"
    End Class
    
    Friend Class StandardMenuGroupIds
        Friend Const Actions As String = "ActionsMenu"
        Friend Const ActionsSurvey As String = "ActionsMenuForSurvey"
        Friend Const NewMenu As String = "NewMenu"
        Friend Const Settings As String = "SettingsMenu"
        Friend Const SettingsSurvey As String = "SettingsMenuForSurvey"
        Friend Const SiteActions As String = "SiteActions"
        Friend Const Upload As String = "UploadMenu"
        Friend Const ViewSelector As String = "ViewSelectorMenu"
    End Class
    
    Friend Class ListEditGroupIds
        Friend Const Communications As String = "Communications"
        Friend Const GeneralSettings As String = "GeneralSettings"
        Friend Const Permissions As String = "Permissions"
    End Class
    
    Friend Class DefaultTextBoxStrings
        Friend Const TitleText As String = "Replace this with your title"
        Friend Const DescriptionText As String = "Replace this with your description"
        Friend Const UrlText As String = "~site/Lists/Tasks/AllItems.aspx"
    End Class
    
    
    namespace ItemTemplateWizard
    {
        // This sample only supports several custom action locations and their group IDs. 
        internal class CustomActionLocations
        {
            internal const string ListEdit = "Microsoft.SharePoint.ListEdit";
            internal const string StandardMenu = "Microsoft.SharePoint.StandardMenu";
        }
    
        internal class StandardMenuGroupIds
        {
            internal const string Actions = "ActionsMenu";
            internal const string ActionsSurvey = "ActionsMenuForSurvey";
            internal const string NewMenu = "NewMenu";
            internal const string Settings = "SettingsMenu";
            internal const string SettingsSurvey = "SettingsMenuForSurvey";
            internal const string SiteActions = "SiteActions";
            internal const string Upload = "UploadMenu";
            internal const string ViewSelector = "ViewSelectorMenu";
        }
    
        internal class ListEditGroupIds
        {
            internal const string Communications = "Communications";
            internal const string GeneralSettings = "GeneralSettings";
            internal const string Permissions = "Permissions";
        }
    
        internal class DefaultTextBoxStrings
        {
            internal const string TitleText = "Replace this with your title";
            internal const string DescriptionText = "Replace this with your description";
            internal const string UrlText = "~site/Lists/Tasks/AllItems.aspx";
        }
    }
    

Creating the Wizard UI

Add XAML to define the UI of the wizard, and add some code to bind some of the controls in the wizard to the ID strings. The wizard that you create resembles the built-in wizard for SharePoint projects in Visual Studio 2010.

To create the wizard UI

  1. In the ItemTemplateWizard project, double-click the WizardWindow.xaml file to open the window in the designer.

  2. In the XAML view of the designer, replace the current XAML with the following XAML. The XAML defines a UI that includes a heading, controls for specifying the behavior of the custom action, and navigation buttons at the bottom of the window.

    Note

    Your project will have some compile errors after you add this XAML to it. These errors will go away when you add code in later steps.

    <ui:DialogWindow x:Class="ItemTemplateWizard.WizardWindow"
                     xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
                     xmlns:ui="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.10.0"        
                     xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
                     Title="SharePoint Customization Wizard" Height="500" Width="700" ResizeMode="NoResize" 
                     Loaded="Window_Loaded" TextOptions.TextFormattingMode="Display">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="75*" />
                <RowDefinition Height="364*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="60*" />
            </Grid.RowDefinitions>
            <Grid Grid.Row="0" Name="headingGrid" Background="White">
                <Label Grid.Row="0" Content="Configure the Custom Action" Name="pageHeaderLabel" HorizontalAlignment="Left" 
                       VerticalAlignment="Center" Margin="18,0,0,0" FontWeight="ExtraBold" />
            </Grid>
            <Grid Grid.Row="1" Name="mainGrid">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="20*" />
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="400*" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <StackPanel Grid.Row="0" Grid.Column="1" Orientation="Vertical">
                    <Label Margin="0,20,0,0" Content="Location:" Name="locationLabel" FontWeight="Bold" />
                    <RadioButton Content="_List Edit" Margin="5,0,0,0" Name="listEditRadioButton" 
                                 Checked="listEditRadioButton_Checked" FontWeight="Normal"  />
                    <RadioButton Content="_Standard Menu" Margin="5,5,0,0" Name="standardMenuRadioButton" 
                                 Checked="standardMenuRadioButton_Checked" FontWeight="Normal" />
                </StackPanel>
                <Label Grid.Row="1" Grid.Column="1" Margin="0,15,0,0" Content="_Group ID:" Name="groupIdLabel" 
                       FontWeight="Bold" Target="{Binding ElementName=idComboBox}" />
                <ComboBox Grid.Row="1" Grid.Column="2" HorizontalAlignment="Left" Margin="0,15,0,0" Height="23" 
                          Width="253" Name="idComboBox" IsEditable="False" IsSynchronizedWithCurrentItem="True" />
                <Label Grid.Row="2" Grid.Column="1" Margin="0,15,0,0" Content="_Title:" Name="titleLabel" 
                       FontWeight="Bold" Target="{Binding ElementName=titleTextBox}" />
                <TextBox Grid.Row="2" Grid.Column="2" HorizontalAlignment="Left" Margin="0,15,0,0" Height="23" 
                         Name="titleTextBox" Width="410" Text="" />
                <Label Grid.Row="3" Grid.Column="1" Margin="0,15,0,0" Content="_Description:" Name="descriptionLabel" 
                       FontWeight="Bold" Target="{Binding ElementName=descriptionTextBox}" />
                <TextBox Grid.Row="3" Grid.Column="2" HorizontalAlignment="Left" Margin="0,15,0,0" Height="23" 
                         Name="descriptionTextBox" Width="410" Text="" />
                <Label Grid.Row="4" Grid.Column="1" Margin="0,15,0,0" Content="_URL:" Height="28" Name="urlLabel" 
                       FontWeight="Bold" Target="{Binding ElementName=urlTextBox}" />
                <TextBox Grid.Row="4" Grid.Column="2" HorizontalAlignment="Left" Margin="0,15,0,0" Height="23" 
                         Name="urlTextBox" Width="410" Text="" />
            </Grid>
            <Rectangle Grid.Row="2" Name="separatorRectangle" Fill="White"  />
            <StackPanel Grid.Row="3" Name="navigationPanel" Orientation="Horizontal">
                <Button Content="_Finish" Margin="500,0,0,0" Height="25" Name="finishButton" Width="85" 
                        Click="finishButton_Click" IsDefault="True" />
                <Button Content="Cancel" Margin="10,0,0,0" Height="25" Name="cancelButton" Width="85" IsCancel="True" />
            </StackPanel>
        </Grid>
    </ui:DialogWindow>
    

    Note

    The window that is created in this XAML is derived from the DialogWindow base class. When you add a custom WPF dialog box to Visual Studio, it is recommended that you derive your dialog box from this class to have consistent styling with other Visual Studio dialog boxes and to avoid modal dialog issues that might otherwise occur. For more information, see How to: Create and Manage Dialog Boxes.

  3. If you are developing a Visual Basic project, remove the ItemTemplateWizard namespace from the WizardWindow class name in the x:Class attribute of the Window element. This is in the first line of the XAML. When you are done, the first line should look like the following.

    <Window x:Class="WizardWindow"
    
  4. Open the code-behind file for the WizardWindow.xaml file.

  5. Replace the code in this file with the following code.

    Public Class WizardWindow
        Private standardMenuGroups As List(Of String)
        Private listEditGroups As List(Of String)
        Private standardMenuGroupIdBinding As Binding
        Private listEditGroupIdBinding As Binding
        Private standardMenuGroupIdBindingView As ListCollectionView
        Private listEditGroupIdBindingView As ListCollectionView
    
        Private Sub Window_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
            standardMenuGroups = New List(Of String) From {
                StandardMenuGroupIds.Actions,
                StandardMenuGroupIds.ActionsSurvey,
                StandardMenuGroupIds.NewMenu,
                StandardMenuGroupIds.Settings,
                StandardMenuGroupIds.SettingsSurvey,
                StandardMenuGroupIds.SiteActions,
                StandardMenuGroupIds.Upload,
                StandardMenuGroupIds.ViewSelector}
            listEditGroups = New List(Of String) From {
                ListEditGroupIds.Communications,
                ListEditGroupIds.GeneralSettings,
                ListEditGroupIds.Permissions}
    
            standardMenuGroupIdBinding = New Binding()
            standardMenuGroupIdBinding.Source = standardMenuGroups
            listEditGroupIdBinding = New Binding()
            listEditGroupIdBinding.Source = listEditGroups
    
            standardMenuGroupIdBindingView = CType(CollectionViewSource.GetDefaultView(standardMenuGroups), ListCollectionView)
            listEditGroupIdBindingView = CType(CollectionViewSource.GetDefaultView(listEditGroups), ListCollectionView)
    
            standardMenuRadioButton.IsChecked = True
        End Sub
    
        Private Sub standardMenuRadioButton_Checked(ByVal sender As Object, ByVal e As RoutedEventArgs)
            BindingOperations.ClearBinding(idComboBox, ComboBox.ItemsSourceProperty)
            idComboBox.SetBinding(ComboBox.ItemsSourceProperty, standardMenuGroupIdBinding)
            standardMenuGroupIdBindingView.MoveCurrentToFirst()
        End Sub
    
        Private Sub listEditRadioButton_Checked(ByVal sender As Object, ByVal e As RoutedEventArgs)
            BindingOperations.ClearBinding(idComboBox, ComboBox.ItemsSourceProperty)
            idComboBox.SetBinding(ComboBox.ItemsSourceProperty, listEditGroupIdBinding)
            listEditGroupIdBindingView.MoveCurrentToFirst()
        End Sub
    
        Private Sub finishButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Me.DialogResult = True
            Me.Close()
        End Sub
    End Class
    
    using System.Collections.Generic;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using Microsoft.VisualStudio.PlatformUI;
    
    namespace ItemTemplateWizard
    {
        public partial class WizardWindow : DialogWindow
        {
            private List<string> standardMenuGroups;
            private List<string> listEditGroups;
            private Binding standardMenuGroupIdBinding;
            private Binding listEditGroupIdBinding;
            private ListCollectionView standardMenuGroupIdBindingView;
            private ListCollectionView listEditGroupIdBindingView;
    
            public WizardWindow()
            {
                InitializeComponent();
            }
    
            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                standardMenuGroups = new List<string>() { 
                    StandardMenuGroupIds.Actions,
                    StandardMenuGroupIds.ActionsSurvey,
                    StandardMenuGroupIds.NewMenu, 
                    StandardMenuGroupIds.Settings, 
                    StandardMenuGroupIds.SettingsSurvey,
                    StandardMenuGroupIds.SiteActions, 
                    StandardMenuGroupIds.Upload, 
                    StandardMenuGroupIds.ViewSelector };
                listEditGroups = new List<string>() { 
                    ListEditGroupIds.Communications, 
                    ListEditGroupIds.GeneralSettings,
                    ListEditGroupIds.Permissions };
    
                standardMenuGroupIdBinding = new Binding();
                standardMenuGroupIdBinding.Source = standardMenuGroups;
                listEditGroupIdBinding = new Binding();
                listEditGroupIdBinding.Source = listEditGroups;
    
                standardMenuGroupIdBindingView = (ListCollectionView)CollectionViewSource.GetDefaultView(standardMenuGroups);
                listEditGroupIdBindingView = (ListCollectionView)CollectionViewSource.GetDefaultView(listEditGroups);
    
                standardMenuRadioButton.IsChecked = true;
            }
    
            private void standardMenuRadioButton_Checked(object sender, RoutedEventArgs e)
            {
                BindingOperations.ClearBinding(idComboBox, ComboBox.ItemsSourceProperty);
                idComboBox.SetBinding(ComboBox.ItemsSourceProperty, standardMenuGroupIdBinding);
                standardMenuGroupIdBindingView.MoveCurrentToFirst();
            }
    
            private void listEditRadioButton_Checked(object sender, RoutedEventArgs e)
            {
                BindingOperations.ClearBinding(idComboBox, ComboBox.ItemsSourceProperty);
                idComboBox.SetBinding(ComboBox.ItemsSourceProperty, listEditGroupIdBinding);
                listEditGroupIdBindingView.MoveCurrentToFirst();
            }
    
            private void finishButton_Click(object sender, RoutedEventArgs e)
            {
                this.DialogResult = true;
                this.Close();
            }
        }
    }
    

Implementing the Wizard

Define the functionality of the wizard by implementing the IWizard interface.

To implement the wizard

  1. In the ItemTemplateWizard project, open the CustomActionWizard code file.

  2. Replace the code in this file with the following code.

    Imports EnvDTE
    Imports Microsoft.VisualStudio.TemplateWizard
    Imports System
    Imports System.Collections.Generic
    
    Public Class CustomActionWizard
        Implements IWizard
    
        Private wizardPage As WizardWindow
    
    #Region "IWizard Methods"
    
        Public Sub RunStarted(ByVal automationObject As Object, ByVal replacementsDictionary As Dictionary(Of String, String), _
            ByVal runKind As WizardRunKind, ByVal customParams() As Object) Implements IWizard.RunStarted
            wizardPage = New WizardWindow()
            Dim dialogCompleted? As Boolean = wizardPage.ShowModal()
    
            If (dialogCompleted = True) Then
                PopulateReplacementDictionary(replacementsDictionary)
            Else
                Throw New WizardCancelledException()
            End If
        End Sub
    
        ' Always return true; this IWizard implementation throws a WizardCancelledException
        ' that is handled by Visual Studio if the user cancels the wizard.
        Public Function ShouldAddProjectItem(ByVal filePath As String) As Boolean _
            Implements IWizard.ShouldAddProjectItem
            Return True
        End Function
    
        ' The following IWizard methods are not implemented in this example.
        Public Sub BeforeOpeningFile(ByVal projectItem As ProjectItem) _
            Implements IWizard.BeforeOpeningFile
        End Sub
    
        Public Sub ProjectFinishedGenerating(ByVal project As Project) _
            Implements IWizard.ProjectFinishedGenerating
        End Sub
    
        Public Sub ProjectItemFinishedGenerating(ByVal projectItem As ProjectItem) _
            Implements IWizard.ProjectItemFinishedGenerating
        End Sub
    
        Public Sub RunFinished() Implements IWizard.RunFinished
        End Sub
    
    #End Region
    
        Private Sub PopulateReplacementDictionary(ByVal replacementsDictionary As Dictionary(Of String, String))
    
            ' Fill in the replacement values from the UI selections on the wizard page. These values are automatically inserted
            ' into the Elements.xml file for the custom action.
            Dim locationValue As String = If(wizardPage.standardMenuRadioButton.IsChecked,
                    CustomActionLocations.StandardMenu, CustomActionLocations.ListEdit)
            replacementsDictionary.Add("$LocationValue$", locationValue)
            replacementsDictionary.Add("$GroupIdValue$", CType(wizardPage.idComboBox.SelectedItem, String))
            replacementsDictionary.Add("$IdValue$", Guid.NewGuid().ToString())
    
            Dim titleText As String = DefaultTextBoxStrings.TitleText
            If False = String.IsNullOrEmpty(wizardPage.titleTextBox.Text) Then
                titleText = wizardPage.titleTextBox.Text
            End If
    
            Dim descriptionText As String = DefaultTextBoxStrings.DescriptionText
            If False = String.IsNullOrEmpty(wizardPage.descriptionTextBox.Text) Then
                descriptionText = wizardPage.descriptionTextBox.Text
            End If
    
            Dim urlText As String = DefaultTextBoxStrings.UrlText
            If False = String.IsNullOrEmpty(wizardPage.urlTextBox.Text) Then
                urlText = wizardPage.urlTextBox.Text
            End If
    
            replacementsDictionary.Add("$TitleValue$", titleText)
            replacementsDictionary.Add("$DescriptionValue$", descriptionText)
            replacementsDictionary.Add("$UrlValue$", urlText)
        End Sub
    End Class
    
    using EnvDTE;
    using Microsoft.VisualStudio.TemplateWizard;
    using System;
    using System.Collections.Generic;
    
    namespace ItemTemplateWizard
    {
        public class CustomActionWizard : IWizard
        {
            private WizardWindow wizardPage;
    
            public CustomActionWizard()
            {
            }
    
            #region IWizard Methods
    
            public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, 
                WizardRunKind runKind, object[] customParams)
            {
                wizardPage = new WizardWindow();
                Nullable<bool> dialogCompleted = wizardPage.ShowModal();
    
                if (dialogCompleted == true)
                {
                    PopulateReplacementDictionary(replacementsDictionary);
                }
                else
                {
                    throw new WizardCancelledException();
                }
            }
    
            // Always return true; this IWizard implementation throws a WizardCancelledException
            // that is handled by Visual Studio if the user cancels the wizard.
            public bool ShouldAddProjectItem(string filePath)
            {
                return true;
            }
    
            // The following IWizard methods are not implemented in this example.
            public void BeforeOpeningFile(ProjectItem projectItem)
            {
            }
    
            public void ProjectFinishedGenerating(Project project)
            {
            }
    
            public void ProjectItemFinishedGenerating(ProjectItem projectItem)
            {
            }
    
            public void RunFinished()
            {
            }
    
            #endregion
    
            private void PopulateReplacementDictionary(Dictionary<string, string> replacementsDictionary)
            {
                // Fill in the replacement values from the UI selections on the wizard page. These values are automatically inserted
                // into the Elements.xml file for the custom action.
                string locationValue = (bool)wizardPage.standardMenuRadioButton.IsChecked ?
                    CustomActionLocations.StandardMenu : CustomActionLocations.ListEdit;
                replacementsDictionary.Add("$LocationValue$", locationValue);
                replacementsDictionary.Add("$GroupIdValue$", (string)wizardPage.idComboBox.SelectedItem);
                replacementsDictionary.Add("$IdValue$", Guid.NewGuid().ToString());
    
                string titleText = DefaultTextBoxStrings.TitleText;
                if (!String.IsNullOrEmpty(wizardPage.titleTextBox.Text))
                {
                    titleText = wizardPage.titleTextBox.Text;
                }
    
                string descriptionText = DefaultTextBoxStrings.DescriptionText;
                if (!String.IsNullOrEmpty(wizardPage.descriptionTextBox.Text))
                {
                    descriptionText = wizardPage.descriptionTextBox.Text;
                }
    
                string urlText = DefaultTextBoxStrings.UrlText;
                if (!String.IsNullOrEmpty(wizardPage.urlTextBox.Text))
                {
                    urlText = wizardPage.urlTextBox.Text;
                }
    
                replacementsDictionary.Add("$TitleValue$", titleText);
                replacementsDictionary.Add("$DescriptionValue$", descriptionText);
                replacementsDictionary.Add("$UrlValue$", urlText);
            }
        }
    }
    

Checkpoint

At this point in the walkthrough, all the code for the wizard is now in the project. Build the project to make sure that it compiles without errors.

To build your project

  • On the Build menu, select Build Solution.

Associating the Wizard with the Item Template

Now that you have implemented the wizard, you must associate the wizard with the Custom Action item template. There are three main steps you must complete to do this:

  1. Sign the wizard assembly with a strong name.

  2. Get the public key token for the wizard assembly.

  3. Add a reference to the wizard assembly in the .vstemplate file for the Custom Action item template.

To sign the wizard assembly with a strong name

  1. In Solution Explorer, right-click the ItemTemplateWizard project node and click Properties.

  2. Click the Signing tab.

  3. Select the Sign the assembly check box.

  4. In the Choose a strong name key file drop-down list, select <New...>.

  5. In the Create Strong Name Key dialog box, enter a name and clear the Protect my key file with a password check box.

  6. Click OK.

  7. On the Build menu, select Build Solution.

To get the public key token for the wizard assembly

  1. Open a Visual Studio Command Prompt window.

  2. Run the following command. Replace path to wizard assembly with the full path to the built ItemTemplateWizard.dll assembly for the ItemTemplateWizard project on your development computer.

    sn.exe -T path to wizard assembly
    

    The public key token for the ItemTemplateWizard.dll assembly is written to the Visual Studio Command Prompt window.

  3. Keep the Visual Studio Command Prompt window open. You will need the public key token during the next procedure.

To add a reference to the wizard assembly in the .vstemplate file

  1. In Solution Explorer, expand the ItemTemplate project node and open the ItemTemplate.vstemplate file.

  2. Near the end of the file, add the following WizardExtension element between the </TemplateContent> and </VSTemplate> tags. Replace the your token value of the PublicKeyToken attribute with the public key token that you obtained in the previous procedure.

    <WizardExtension>
      <Assembly>ItemTemplateWizard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=your token</Assembly>
      <FullClassName>ItemTemplateWizard.CustomActionWizard</FullClassName>
    </WizardExtension>
    

    For more information about the WizardExtension element, see WizardExtension Element (Visual Studio Templates).

  3. Save and close the file.

Adding Replaceable Parameters to the Elements.xml File in the Item Template

Add several replaceable parameters to the Elements.xml file in the ItemTemplate project. These parameters are initialized in the PopulateReplacementDictionary method in the CustomActionWizard class that you defined earlier. When a user adds a Custom Action project item to a project, Visual Studio automatically replaces these parameters in the Elements.xml file in the new project item with the values that they specified in the wizard.

A replaceable parameter is a token that begins and ends with the dollar sign ($) character. In addition to defining your own replaceable parameters, you can use built-in parameters that are defined and initialized by the SharePoint project system. For more information, see Replaceable Parameters.

To add replaceable parameters to the Elements.xml file

  1. Open the Elements.xml file in the ItemTemplate project.

  2. Replace the contents of this file with the following XML.

    <?xml version="1.0" encoding="utf-8" ?>
    <Elements Id="$guid8$" xmlns="https://schemas.microsoft.com/sharepoint/">
      <CustomAction Id="$IdValue$"
                    GroupId="$GroupIdValue$"
                    Location="$LocationValue$"
                    Sequence="1000"
                    Title="$TitleValue$"
                    Description="$DescriptionValue$" >
        <UrlAction Url="$UrlValue$"/>
      </CustomAction>
    </Elements>
    

    The new XML changes the values of the Id, GroupId, Location, Description, and Url attributes to replaceable parameters.

  3. Save and close the file.

Adding the Wizard to the VSIX Package

To deploy the wizard with the VSIX package that contains the project item, add a reference to the wizard project to the source.extension.vsixmanifest file in the VSIX project.

To add the wizard to the VSIX package

  1. In Solution Explorer, double-click the source.extension.vsixmanifest file in the CustomActionProjectItem project.

    Visual Studio opens the file in the manifest editor.

  2. In the Content section of the editor, click the Add Content button.

  3. In the Add Content dialog box, in the Select a content type list box, select Template Wizard.

  4. Under Select a source, click the Project radio button, and select ItemTemplateWizard in the list box next to it.

  5. Click OK.

  6. On the Build menu, click Build Solution. Make sure that the solution compiles without errors.

Testing the Wizard

You are now ready to test the wizard. First, start debugging the CustomActionProjectItem solution in the experimental instance of Visual Studio. Then, test the wizard for the Custom Action project item in a SharePoint project in the experimental instance of Visual Studio. Finally, build and run the SharePoint project to verify that the custom action works as expected.

To start debugging the solution

  1. Restart Visual Studio with administrator privileges and open the CustomActionProjectItem solution.

  2. In the ItemTemplateWizard project, open the CustomActionWizard code file and add a breakpoint to the first line of code in the RunStarted method.

  3. On the Debug menu, click Exceptions.

  4. In the Exceptions dialog, make sure that the Thrown and User-unhandled check boxes for Common Language Runtime Exceptions are cleared.

  5. Click OK.

  6. Press F5 to start debugging.

    Visual Studio installs the extension to %UserProfile%\AppData\Local\Microsoft\VisualStudio\10.0Exp\Extensions\Contoso\Custom Action Project Item\1.0 and starts an experimental instance of Visual Studio. You will test the project item in this instance of Visual Studio.

To test the wizard in Visual Studio

  1. In the experimental instance of Visual Studio, on the File menu, point to New, and then click Project.

  2. Expand Visual C# or Visual Basic (depending on the language your item template supports), expand SharePoint, and then click 2010.

  3. In the list of project templates, click Empty Project.

  4. In the Name box, type CustomActionWizardTest.

  5. Click OK.

  6. In the SharePoint Customization Wizard, type the URL of the site that you want to use for debugging, and click Finish.

  7. In Solution Explorer, right-click the project node, point to Add, and then click New Item.

  8. In the Add New Item dialog box, click the 2010 node under the SharePoint node.

  9. In the list of project items, click Custom Action and then click Add.

  10. Verify that the code in the other instance of Visual Studio stops on the breakpoint that you set earlier in the RunStarted method. Press F5 to continue to debug the project.

  11. In the wizard, make the following selections:

    • Under Location, click List Edit.

    • For Group ID, click Communications.

    • For Title, type SharePoint Developer Center.

    • For Description, type Opens the SharePoint Developer Center Web site.

    • For URL, type https://msdn.microsoft.com/sharepoint/default.aspx.

  12. Click Finish.

    Visual Studio adds a new item named CustomAction1 to your project, and it opens the Elements.xml file in the editor. Verify that Elements.xml contains the values that you specified in the wizard.

To test the custom action in SharePoint

  1. In the experimental instance of Visual Studio, press F5. The custom action is packaged and deployed to the SharePoint site specified by the Site URL property of the project. The Web browser opens to the default page of this site.

    Note

    If the Script Debugging Disabled dialog box is displayed, click Yes to continue to debug the project.

  2. In the Quick Launch area, click Tasks.

  3. On the Ribbon, click the List tab.

  4. In the Settings group, click List Settings.

  5. Under the Communications heading near the top of the page, verify that a link with the text SharePoint Developer Center appears.

  6. Click the SharePoint Developer Center link. Verify that the browser opens the Web site https://msdn.microsoft.com/sharepoint/default.aspx.

  7. Close the Web browser.

Cleaning up the Development Computer

After you finish testing the project item, remove the project item template from the experimental instance of Visual Studio.

To clean up the development computer

  1. In the experimental instance of Visual Studio, on the Tools menu, click Extension Manager.

    The Extension Manager dialog box opens.

  2. In the list of extensions, click Custom Action Project Item, and then click Uninstall.

  3. In the dialog box that appears, click Yes to confirm that you want to uninstall the extension.

  4. Click Restart Now to complete the uninstallation.

  5. Close both instances of Visual Studio (the experimental instance and the instance of Visual Studio that has the CustomActionProjectItem solution open).

See Also

Tasks

Walkthrough: Creating a Custom Action Project Item with an Item Template, Part 1

How to: Use Wizards with Project Templates

Reference

Visual Studio Template Schema Reference

IWizard

Concepts

Defining Custom SharePoint Project Item Types

Creating Item Templates and Project Templates for SharePoint Project Items

Other Resources

Default Custom Action Locations and IDs