演练:使用项模板创建自定义操作项目项(第 2 部分)

在定义 SharePoint 项目项的自定义类型并将其与 Visual Studio 中的项模板关联后,可能还需要提供模板向导。 当用户使用模板向项目中添加项目项的新实例时,您可以使用此向导收集用户的信息。 收集的信息可用于初始化项目项。

在本演练中,您将为演练:使用项模板创建自定义操作项目项(第 1 部分)中演示的“自定义操作”项目项添加向导。 当用户向 SharePoint 项目添加“自定义操作”项目项时,此向导将收集有关自定义操作的信息(如自定义操作的位置和单击自定义操作时将导航到的 URL),并将此信息添加到新项目项的 Elements.xml 文件中。

本演练将演示以下任务:

  • 为与项模板关联的自定义 SharePoint 项目项类型创建向导。

  • 定义一个自定义向导 UI,它类似于 Visual Studio 2010 中的 SharePoint 项目项的内置向导。

  • 通过可替换参数使用此向导中收集的数据来初始化 SharePoint 项目文件。

  • 调试并测试向导。

提示

可从以下位置下载一个示例,该示例包含此演练的已完成项目、代码和其他文件:https://go.microsoft.com/fwlink/?LinkId=191369

系统必备

若要执行本演练,必须先通过完成演练:使用项模板创建自定义操作项目项(第 1 部分)来创建 CustomActionProjectItem 解决方案。

还需要在开发计算机上安装以下组件才能完成本演练:

了解以下概念很有用,但对于完成本演练并不是必需的:

创建向导项目

若要完成此演练,需要向在演练:使用项模板创建自定义操作项目项(第 1 部分)中创建的 CustomActionProjectItem 解决方案添加新项目。 您将实现 IWizard 接口并定义此项目中的向导 UI。

创建向导项目

  1. 在 Visual Studio 中打开 CustomActionProjectItem 解决方案。

  2. 在**“解决方案资源管理器”中,右击解决方案节点,单击“添加”,再单击“新建项目”**。

    提示

    在 Visual Basic 项目中,仅当在“选项”对话框 ->“项目和解决方案”->“常规”中选中“总是显示解决方案”复选框时,解决方案节点才会出现在“解决方案资源管理器”中。

  3. 在**“新建项目”对话框中,展开“Visual C#”“Visual Basic”节点,然后单击“Windows”**节点。

  4. 在**“新建项目”对话框顶部的组合框中,确保选择“.NET Framework 4”**。

  5. 选择**“WPF 用户控件库”**项目模板。

  6. 在**“名称”**框中键入 ItemTemplateWizard。

  7. 单击**“确定”**。

    Visual Studio 将**“ItemTemplateWizard”**项目添加到解决方案中。

  8. 从项目中删除 UserControl1 项。

配置向导项目

在创建向导之前,必须向项目中添加 WPF 窗口、代码文件和程序集引用。

配置向导项目

  1. 在**“解决方案资源管理器”中,右击“ItemTemplateWizard”项目节点,再单击“属性”**。

  2. 在**“项目设计器”中,将目标框架从 .NET Framework 4 Client Profile 更改为 .NET Framework 4。 在 Visual C# 项目中,可以在“应用程序”选项卡上执行此操作;在 Visual Basic 项目中,可以在“编译”**选项卡上执行此操作。 有关更多信息,请参见如何:面向特定的 .NET Framework 版本或配置文件

    提示

    默认情况下,当创建面向 .NET Framework 4 的新项目时,项目将面向客户端配置文件。 本演练需要完整的 .NET Framework 4。

  3. 在 ItemTemplateWizard 项目中,将新的**“窗口(WPF)”项添加到项目中。 将此新项命名为“WizardWindow”**。

  4. 添加两个具有下列名称的代码文件:

    • CustomActionWizard

    • Strings

  5. 在**“项目”菜单上,单击“添加引用”**。

  6. 在**“.NET”选项卡上,按住 Ctrl 的同时单击下列程序集,然后单击“确定”**:

    • EnvDTE

    • Microsoft.VisualStudio.Shell.10.0

    • Microsoft.VisualStudio.TemplateWizardInterface

  7. 在**“解决方案资源管理器”中,在 ItemTemplateWizard 项目的“引用”文件夹下,单击“EnvDTE”**。

    提示

    在 Visual Basic 项目中,“引用”文件夹仅当在“选项”对话框 ->“项目和解决方案”->“常规”中选中“总是显示解决方案”复选框时显示。

  8. 在**“属性”窗口中,将“嵌入互操作类型”属性更改为“False”**。

定义自定义操作的默认位置和 ID 字符串

每个自定义操作都具有一个位置和 ID,二者分别是在 Elements.xml 文件中的 CustomAction 元素的 Location 特性和 GroupID 特性中指定的。 在此步骤中,您将为 ItemTemplateWizard 项目中的这些特性定义一些有效字符串。 完成此演练后,当用户在向导中选择位置和 ID 时,这些字符串将写入“自定义操作”项目项中的 Elements.xml 文件中。

为简单起见,此示例仅支持可用的默认位置和 ID 的一个子集。 有关完整列表,请参见 Default Custom Action Locations and IDs(默认的自定义操作位置和 ID)。

定义默认的位置和 ID 字符串

  1. 在 ItemTemplateWizard 项目中,打开 Strings 代码文件。

  2. 将此文件中的代码替换为以下代码。

    ' 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";
        }
    }
    

创建向导 UI

添加 XAML 以定义向导的 UI,并添加一些代码以将向导中的一些控件绑定到 ID 字符串。 您创建的向导类似于 Visual Studio 2010 中的 SharePoint 项目的内置向导。

创建向导 UI

  1. 在 ItemTemplateWizard 项目中,双击 WizardWindow.xaml 文件以在设计器中打开窗口。

  2. 在设计器的 XAML 视图中,用以下 XAML 替换当前的 XAML。 XAML 定义一个 UI,该 UI 包含一个标题、用于指定自定义操作的行为的控件以及位于窗口底部的导航按钮。

    提示

    在将此 XAML 添加到项目中后,项目将会出现一些编译错误。 在添加后面的步骤中的代码之后,这些错误将消失。

    <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>
    

    提示

    在此 XAML 中创建的窗口派生自 DialogWindow 基类。 在向 Visual Studio 添加自定义 WPF 对话框时,建议您从该类派生对话框,以获得与其他 Visual Studio 对话框一致的样式并避免可能发生的模式对话框问题。 有关更多信息,请参见How to: Create and Manage Dialog Boxes

  3. 如果正在开发 Visual Basic 项目,请从 Window 元素的 x:Class 特性中的 WizardWindow 类名称中移除 ItemTemplateWizard 命名空间。 此命名空间位于 XAML 的第一行中。 完成上述操作以后,第一行应类似于下面这样:

    <Window x:Class="WizardWindow"
    
  4. 打开 WizardWindow.xaml 文件的代码隐藏文件。

  5. 将此文件中的代码替换为以下代码。

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

实现向导

通过实现 IWizard 接口来定义向导的功能。

实现向导

  1. 在 ItemTemplateWizard 项目中,打开 CustomActionWizard 代码文件。

  2. 将此文件中的代码替换为以下代码。

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

检查点

演练进行到此时,向导的所有代码都位于项目中。 生成项目以确保编译项目时不会出错。

生成项目

  • 在**“生成”菜单上,选择“生成解决方案”**。

将向导与项模板关联

现在,您已实现了向导,您必须将向导与**“自定义操作”**项模板关联。 为此,您必须执行以下三个主要步骤:

  1. 用强名称对向导程序集进行签名。

  2. 获取向导程序集的公钥标记。

  3. 在**“自定义操作”**项模板的 .vstemplate 文件中添加对向导程序集的引用。

用强名称对向导程序集进行签名

  1. 在**“解决方案资源管理器”中,右击“ItemTemplateWizard”项目节点,再单击“属性”**。

  2. 单击**“签名”**选项卡。

  3. 选中**“为程序集签名”**复选框。

  4. 在**“选择强名称密钥文件”下拉列表中,选择“<新建...>”**。

  5. 在**“创建强名称密钥”对话框中,输入名称并清除“使用密码保护密钥文件”**复选框。

  6. 单击**“确定”**。

  7. 在**“生成”菜单上,选择“生成解决方案”**。

获取向导程序集的公钥标记

  1. 打开“Visual Studio 命令提示”窗口。

  2. 运行下面的命令。 将 path to wizard assembly 替换为已在开发计算机上为 ItemTemplateWizard 项目生成的 ItemTemplateWizard.dll 程序集的完整路径。

    sn.exe -T path to wizard assembly
    

    ItemTemplateWizard.dll 程序集的公钥标记会写入到 Visual Studio 命令提示符窗口中。

  3. 将 Visual Studio 命令提示符窗口保持打开状态。 在下面的过程中,将需要公钥标记。

在 .vstemplate 文件中添加对向导程序集的引用

  1. 在**“解决方案资源管理器”中,展开“ItemTemplate”**项目节点,然后打开 ItemTemplate.vstemplate 文件。

  2. 在该文件末尾附近的 </TemplateContent> 和 </VSTemplate> 标记之间添加以下 WizardExtension 元素。 将 PublicKeyToken 特性的 your token 值替换为上一过程中获得的公钥标记。

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

    有关 WizardExtension 元素的更多信息,请参见 WizardExtension 元素(Visual Studio 模板)

  3. 保存并关闭文件。

将可替换参数添加到项模板的 Elements.xml 文件中

将多个可替换参数添加到 ItemTemplate 项目中的 Elements.xml 文件中。 将在之前定义的 CustomActionWizard 类的 PopulateReplacementDictionary 方法中初始化这些参数。 当用户向某个项目添加“自定义操作”项目项时,Visual Studio 会自动将新项目项中的 Elements.xml 文件中的这些参数替换为在向导中指定的值。

可替换参数是以美元符号 ($) 字符开始和结束的标记。 除了定义您自己的可替换参数外,还可以使用由 SharePoint 项目系统定义和初始化的内置参数。 有关更多信息,请参见可替换参数

向 Elements.xml 文件添加可替换参数

  1. 在 ItemTemplate 项目中打开 Elements.xml 文件。

  2. 用以下 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>
    

    新的 XML 会将 Id、GroupId、Location、Description 和 Url 特性的值更改为可替换参数。

  3. 保存并关闭文件。

向 VSIX 包添加向导

若要将向导与包含项目项的 VSIX 包一起部署,请将对向导项目的引用添加到 VSIX 项目中的 source.extension.vsixmanifest 文件中。

向 VSIX 包添加向导

  1. 在**“解决方案资源管理器”中,双击 CustomActionProjectItem 项目中的“source.extension.vsixmanifest”**文件。

    Visual Studio 将在清单编辑器中打开该文件。

  2. 在编辑器的**“内容”部分中,单击“添加内容”**按钮。

  3. 在**“添加内容”对话框的“选择内容类型”列表框中,选择“模板向导”**。

  4. 在**“选择源”下,单击“项目”单选按钮,并在其旁边的列表框中选择“ItemTemplateWizard”**。

  5. 单击**“确定”**。

  6. 在**“生成”菜单上,单击“生成解决方案”**。 确保编译解决方案时不会出错。

测试向导

现在已经准备好对向导进行测试。 首先,在 Visual Studio 的实验实例中开始调试 CustomActionProjectItem 解决方案。 然后,在 Visual Studio 的实验实例中,对 SharePoint 项目中的“自定义操作”项目项的向导进行测试。 最后,生成并运行 SharePoint 项目,以验证此自定义操作是否按预期工作。

开始调试解决方案

  1. 利用管理员特权重新启动 Visual Studio,并打开“CustomActionProjectItem”解决方案。

  2. 在 ItemTemplateWizard 项目中,打开 CustomActionWizard 代码文件,并在 RunStarted 方法的第一个代码行中添加一个断点。

  3. 在**“调试”菜单上,单击“异常”**。

  4. 在**“异常”对话框中,确保已清除“公共语言运行时异常”“引发”“用户未处理的”**复选框。

  5. 单击**“确定”**。

  6. 按 F5 开始调试。

    Visual Studio 将扩展安装到 %UserProfile%\AppData\Local\Microsoft\VisualStudio\10.0Exp\Extensions\Contoso\Custom Action Project Item\1.0 中,并启动 Visual Studio 的实验实例。 您将在此 Visual Studio 实例中测试项目项。

在 Visual Studio 中测试向导

  1. 在 Visual Studio 的实验实例中,在**“文件”菜单上指向“新建”,然后单击“项目”**。

  2. 展开**“Visual C#”“Visual Basic”(取决于项模板支持的语言),再展开“SharePoint”,然后单击“2010”**。

  3. 在项目模板的列表中,单击**“空项目”**。

  4. 在**“名称”**框中键入 CustomActionWizardTest。

  5. 单击**“确定”**。

  6. 在**“SharePoint 自定义向导”中,键入要用于调试的网站的 URL,并单击“完成”**。

  7. 在**“解决方案资源管理器”中,右击项目节点,指向“添加”,然后单击“新建项”**。

  8. 在**“添加新项”对话框中,单击“SharePoint”节点下的“2010”**节点。

  9. 在项目项列表中,单击**“自定义操作”,然后单击“添加”**。

  10. 验证另一个 Visual Studio 实例中的代码是否会在您之前在 RunStarted 方法中设置的断点处停止。 按 F5 继续调试该项目。

  11. 在该向导中,进行下列选择:

    • 在**“位置”下,单击“列表编辑”**。

    • 对于**“组 ID”,单击“通信”**。

    • 对于**“标题”**,键入“SharePoint 开发中心”。

    • 对于**“说明”**,键入“打开 SharePoint 开发中心网站”。

    • 对于**“URL”**,键入 https://msdn.microsoft.com/sharepoint/default.aspx。

  12. 单击**“完成”**。

    Visual Studio 会将名为**“CustomAction1”**的新项添加到项目中,并在编辑器中打开 Elements.xml 文件。 验证 Elements.xml 是否包含您在向导中指定的值。

测试 SharePoint 中的自定义操作

  1. 在 Visual Studio 的实验实例中,按 F5。 这将对自定义操作进行打包并将其部署到由项目的**“网站 URL”**属性指定的 SharePoint 网站中。 Web 浏览器将打开此网站的默认页。

    提示

    如果出现“脚本调试被禁用”对话框,请单击“是”继续调试项目。

  2. 在快速启动区域内,单击**“任务”**。

  3. 在功能区上,单击**“列表”**选项卡。

  4. 在**“设置”组中单击“列表设置”**。

  5. 在页的顶部附近的**“通信”标题下,验证是否出现了具有文本“SharePoint 开发中心”**的链接。

  6. 单击**“SharePoint 开发中心”**链接。 确认浏览器已打开网站 https://msdn.microsoft.com/sharepoint/default.aspx。

  7. 关闭 Web 浏览器。

清理开发计算机

测试完项目项之后,从 Visual Studio 的实验实例中移除项目项模板。

清理开发计算机

  1. 在 Visual Studio 的实验实例中,在**“工具”菜单上单击“扩展管理器”**。

    这将打开**“扩展管理器”**对话框。

  2. 在扩展列表中,单击**“自定义操作项目项”,然后单击“卸载”**。

  3. 在出现的对话框中,单击**“是”**以确认您要卸载该扩展。

  4. 单击**“立即重新启动”**以完成卸载。

  5. 关闭 Visual Studio 的两个实例(Visual Studio 的实验实例和 Visual Studio 的已打开 CustomActionProjectItem 解决方案的实例)。

请参见

任务

演练:使用项模板创建自定义操作项目项(第 1 部分)

如何:使用向导来处理项目模板

参考

Visual Studio 模板架构参考

IWizard

其他资源

定义自定义 SharePoint 项目项类型

为 SharePoint 项目项创建项模板和项目模板

默认自定义操作位置和 ID