Partager via


Procédure pas à pas : création d'un élément de projet de colonnes de sites avec un modèle de projet, deuxième partie

Après avoir défini un type personnalisé d'élément de projet SharePoint et l'avoir associé à un modèle de projet dans Visual Studio, vous pouvez également fournir un Assistant pour le modèle.Vous pouvez utiliser l'Assistant pour collecter des informations auprès des utilisateurs lorsqu'ils emploient votre modèle pour créer un projet qui contient l'élément de projet.Les informations que vous collectez peuvent être utilisées pour initialiser l'élément de projet.

Dans cette procédure pas à pas, vous ajouterez un Assistant au modèle de projet Colonne de site qui est illustré dans Procédure pas à pas : création d'un élément de projet de colonnes de sites avec un modèle de projet, première partie.Lorsqu'un utilisateur crée un projet Colonne de site, l'Assistant collecte également des informations sur la colonne de site (par exemple son type de base et groupe) et ajoute ces informations dans le fichier Elements.xml du nouveau projet.

Cette procédure pas à pas présente les tâches suivantes :

  • Création d'un Assistant pour un type d'élément de projet SharePoint personnalisé associé à un modèle de projet.

  • Définition d'une interface utilisateur d'Assistant personnalisé semblable aux assistants intégrés des projets sharepoint dans Visual Studio.

  • Création de deux commandes SharePoint utilisées pour faire appel à un site SharePoint sur l'ordinateur local pendant l'exécution de l'Assistant.Les commandes SharePoint sont des méthodes susceptibles d'être utilisées par les extensions Visual Studio en vue d'appeler des API dans le modèle objet serveur SharePoint.Pour plus d’informations, consultez Appel des modèles d'objet SharePoint.

  • Utilisation de paramètres remplaçables pour initialiser les fichiers de projet SharePoint avec les données que vous collectez dans l'Assistant.

  • Création d'un fichier .snk dans chaque instance du projet Colonne de site.Ce fichier est utilisé pour signer la sortie de projet afin que l'assembly de la solution SharePoint puisse être déployé dans le GAC (Global Assembly Cache).

  • Débogage et test de l'Assistant.

[!REMARQUE]

Vous pouvez télécharger une instance qui contient les projets remplis, de code et d'autres fichiers pour cette procédure pas-à-pas de l'emplacement suivant : https://go.microsoft.com/fwlink/?LinkId=191369.

Composants requis

Pour exécuter cette procédure pas à pas, vous devez d'abord créer la solution SiteColumnProjectItem en suivant la procédure décrite dans Procédure pas à pas : création d'un élément de projet de colonnes de sites avec un modèle de projet, première partie.

Vous avez par ailleurs besoin des composants suivants sur l'ordinateur de développement pour exécuter cette procédure pas à pas :

Une connaissance des concepts suivants est utile, mais pas obligatoire, pour effectuer cette procédure pas à pas :

Présentation des composants de l'Assistant

L'Assistant qui est représenté dans cette procédure pas à pas contient plusieurs composants.Le tableau suivant décrit ces composants.

Composant

Description

Implémentation de l'Assistant

Il s'agit d'une classe nommée SiteColumnProjectWizard qui implémente l'interface IWizard.Cette interface définit les méthodes appelées par Visual Studio lorsque l'Assistant démarre et finit et à certains moments pendant l'exécution de l'Assistant.

Interface utilisateur de l'Assistant

Il s'agit d'une fenêtre WPF nommée WizardWindow.Cette fenêtre se compose de deux contrôles utilisateur nommés Page1 et Page2.Ces contrôles utilisateur représentent les deux pages de l'Assistant.

Dans cette procédure pas à pas, la méthode RunStarted de l'implémentation de l'Assistant affiche l'interface utilisateur de l'Assistant.

Modèle de données de l'Assistant

Il s'agit d'une classe intermédiaire nommée SiteColumnWizardModel qui fournit une couche entre l'interface utilisateur de l'Assistant et l'implémentation de l'Assistant.Cet exemple utilise cette classe pour rendre abstrait le lien entre l'implémentation de l'Assistant et l'interface utilisateur de l'Assistant ; cette classe n'est pas un composant requis de tous les Assistants.

Dans cette procédure pas à pas, l'implémentation de l'Assistant transmet un objet SiteColumnWizardModel dans la fenêtre de l'Assistant lorsque l'interface utilisateur de l'Assistant s'affiche.L'interface utilisateur de l'Assistant utilise des méthodes de cet objet pour enregistrer les valeurs des contrôles de l'interface utilisateur, et pour effectuer des tâches, notamment vérifier que l'URL d'entrée du site est valide.Une fois que l'utilisateur a terminé avec l'Assistant, l'implémentation de l'Assistant utilise l'objet SiteColumnWizardModel pour déterminer l'état final de l'interface utilisateur.

Gestionnaire de signature des projets

Il s'agit d'une classe d'assistance nommée ProjectSigningManager utilisée par l'implémentation de l'Assistant pour créer un fichier key.snk dans chaque nouvelle instance de projet.

Commandes SharePoint

Ce sont des méthodes utilisées par le modèle de données de l'Assistant pour faire appel au site SharePoint local pendant l'exécution de l'Assistant.Étant donné que les commandes SharePoint doivent cibler le .NET Framework 3.5, ces commandes sont implémentées dans un assembly différent du reste du code de l'Assistant.

Création du projet

Pour exécuter cette procédure pas à pas, vous devez ajouter plusieurs projets à la solution SiteColumnProjectItem que vous avez créée dans Procédure pas à pas : création d'un élément de projet de colonnes de sites avec un modèle de projet, première partie :

  • Un projet WPF.Vous implémenterez l'interface IWizard et définirez l'interface utilisateur de l'Assistant dans ce projet.

  • Un projet de bibliothèque de classes qui définit les commandes SharePoint.Ce projet doit cibler .NET Framework 3.5.

Démarrez la procédure pas à pas en créant les projets.

Pour créer le projet WPF

  1. Dans Visual Studio, ouvrez la solution SiteColumnProjectItem.

  2. Dans Explorateur de solutions, ouvrez le menu contextuel du nœud de solution SiteColumnProjectItem , choisissez Ajouter, puis choisissez Nouveau projet.

    [!REMARQUE]

    Dans les projets Visual Basic, le nœud de la solution s'affiche uniquement lorsque la case à cocher Toujours afficher la solution est activée dans la General, Projects and Solutions, Options Dialog Box.

  3. En haut de la boîte de dialogue Ajouter un nouveau projet , assurez -vous que .NET Framework 4,5 est sélectionnez dans la liste des versions du .NET Framework.

  4. Développez le nœud Visual C# ou le nœud Visual Basic , puis sélectionnez le nœud Fenêtres .

  5. Dans la liste des modèles de projet, choisissez Bibliothèque de contrôles utilisateur WPF, nommez le projet ProjectTemplateWizard, puis choisissez le bouton OK .

    Visual Studio ajoute le projet ProjectTemplateWizard à la solution et ouvre le fichier de la valeur par défaut UserControl1.xaml.

  6. Supprimez le fichier UserControl1.xaml du projet.

Pour créer le projet de commandes SharePoint

  1. Dans Explorateur de solutions, ouvrez le menu contextuel du nœud de solution SiteColumnProjectItem, choisissez Ajouter, puis choisissez Nouveau projet.

  2. En haut de la boîte de dialogue Ajouter un nouveau projet , choisissez .NET Framework 3.5 dans la liste des versions du .NET Framework.

  3. Développez le nœud Visual C# ou le nœud Visual Basic , puis sélectionnez le nœud Fenêtres .

  4. Choisissez le modèle de projet Bibliothèque de classes , nommez le projet SharePointCommands, puis choisissez le bouton OK .

    Visual Studio ajoute le projet SharePointCommands à la solution et ouvre le fichier de code Class1 par défaut.

  5. Supprimez le fichier de code Class1 du projet.

Configuration des projets

Avant de créer l'assistant, vous devez ajouter des fichiers et références d'assembly de code aux projets.

Pour configurer le projet d'Assistant

  1. Dans Explorateur de solutions, ouvrez le menu contextuel du nœud de projet ProjectTemplateWizard , puis choisissez Propriétés.

  2. Dans Concepteur de projets, sélectionnez l'onglet Application pour un projet visual C# ou l'onglet Compiler pour un projet Visual Basic.

  3. Assurez -vous que la version cible du. Net Framework est défini sur .NET Framework 4,5, pas.NET Framework 4,5 client profile.

    Pour plus d’informations, consultez Comment : cibler une version du .NET Framework.

  4. Ouvrez le menu contextuel du projet ProjectTemplateWizard , choisissez Ajouter, puis choisissez Nouvel élément.

  5. Sélectionnez l'élément fenêtre (WPF) , nommez l'élément WizardWindow, puis choisissez le bouton Ajouter .

  6. Ajoutez deux éléments contrôle utilisateur (WPF) au projet, et nommez-les Page1 et Page2.

  7. Ajoutez quatre fichiers de code au projet, et donnez leur les noms suivants :

    • SiteColumnProjectWizard

    • SiteColumnWizardModel

    • ProjectSigningManager

    • CommandIds

  8. Ouvrez le menu contextuel du nœud de projet ProjectTemplateWizard , puis choisissez Ajouter une référence.

  9. Développez le nœud Assemblys , sélectionnez le nœud Extensions , puis activez les cases à cocher en regard de les assemblys suivants :

    • EnvDTE

    • Microsoft.VisualStudio.OLE.Interop

    • Microsoft.VisualStudio.SharePoint

    • Microsoft.VisualStudio.Shell.11.0

    • Microsoft.VisualStudio.Shell.Interop.10.0

    • Microsoft.VisualStudio.Shell.Interop.11.0

    • Microsoft.VisualStudio.TemplateWizardInterface

  10. Choisissez le bouton OK pour ajouter des assemblys au projet.

  11. Dans Explorateur de solutions, sous le dossier Références pour le projet ProjectTemplateWizard , choisissez EnvDTE.

    [!REMARQUE]

    Dans les projets Visual Basic, le dossier Références s'affiche uniquement si la case Toujours afficher la solution est cochée dans la General, Projects and Solutions, Options Dialog Box.

  12. Dans la fenêtre Propriétés , remplacez la valeur de la propriété Embed Interop Types par False.

  13. Si vous développez un projet Visual Basic, importez l'espace de noms d' ProjectTemplateWizard dans votre projet à l'aide Concepteur de projets.

    Pour plus d’informations, consultez Comment : ajouter ou supprimer des espaces de noms importés (Visual Basic).

Pour configurer le projet SharePointCommands

  1. Dans Explorateur de solutions, sélectionnez le nœud de projet SharePointCommands .

  2. Dans la barre de menus, sélectionnez Projet, Ajouter un élément existant.

  3. Dans la boîte de dialogue Ajouter un élément existant , accédez au dossier qui contient les fichiers de code pour le projet ProjectTemplateWizard, puis sélectionnez le fichier de code CommandIds .

  4. Cliquez sur la flèche en regard de le bouton Ajouter , puis choisissez l'option Ajoutez en tant que lien dans le menu qui s'affiche.

    Visual Studio ajoute le fichier de code au projet SharePointCommands en tant que lien.Le fichier de code se trouve dans le projet ProjectTemplateWizard , mais le code dans le fichier est également compilé dans le projet SharePointCommands .

  5. Dans le projet SharePointCommands , ajoutez un autre fichier de code appelé Commands.

  6. Sélectionnez le projet SharePointCommands, puis, dans la barre de menus, sélectionnez Projet, Ajouter une référence.

  7. Développez le nœud Assemblys , sélectionnez le nœud Extensions , puis activez les cases à cocher en regard de les assemblys suivants :

    • Microsoft.SharePoint

    • Microsoft.VisualStudio.SharePoint.Commands

  8. Choisissez le bouton OK pour ajouter des assemblys au projet.

Création du modèle d'Assistant, du gestionnaire de signature et des ID des commandes SharePoint

Ajoutez le code au projet ProjectTemplateWizard pour implémenter les composants suivants dans l'exemple :

  • Les ID des commandes SharePoint.Ces chaînes identifient les commandes SharePoint que l'assistant.À une étape ultérieure de cette procédure, vous ajouterez le code au projet SharePointCommands pour implémenter les commandes.

  • Le modèle de données de l'Assistant.

  • Le gestionnaire de signature du projet.

Pour plus d'informations sur ces composants, consultez Présentation des composants de l'Assistant.

Pour définir les ID des commandes SharePoint

  • Dans le projet ProjectTemplateWizard, ouvrez le fichier de code CommandIds, puis remplacez le contenu du fichier entier par le code suivant.

    Namespace Contoso.SharePoint.Commands
        Public Class CommandIds
            Public Const GetFieldTypes As String = "Contoso.Commands.GetFieldTypes"
            Public Const ValidateSite As String = "Contoso.Commands.ValidateSite"
        End Class
    End Namespace
    
    namespace Contoso.SharePoint.Commands
    {
        public static class CommandIds
        {
            public const string GetFieldTypes = "Contoso.Commands.GetFieldTypes";
            public const string ValidateSite = "Contoso.Commands.ValidateSite";
        }
    }
    

Pour créer le modèle d'Assistant

  • Ouvrez le fichier de code SiteColumnWizardModel, puis remplacez le contenu du fichier entier par le code suivant.

    Imports EnvDTE
    Imports Microsoft.VisualStudio.SharePoint
    Imports Microsoft.VisualStudio
    Imports Microsoft.VisualStudio.Shell
    Imports Microsoft.VisualStudio.Shell.Interop
    Imports IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider
    
    Public Class SiteColumnWizardModel
        Private dteObject As DTE
        Private projectServiceValue As ISharePointProjectService
        Private validatedUrls As New List(Of String)
    
        Friend Sub New(ByVal dteObject As DTE, ByVal requiresFarmPriveleges As Boolean)
            Me.dteObject = dteObject
    
            ' Initialize default values for wizard choices.
            IsSandboxed = Not requiresFarmPriveleges
            IsSecondPagePopulated = False
            FieldType = "Text"
            FieldGroup = "Custom Columns"
            FieldName = "My Custom Column"
            CurrentSiteUrl = GetLocalHostUrl()
        End Sub
    
    #Region "Helper methods used by the wizard UI"
    
        ' Specifies whether the current site URL is valid. Uses the ValidateSite SharePoint command to do this.
        Friend Function ValidateCurrentUrl(ByVal errorMessage As String) As Boolean
            Dim isValid As Boolean = False
            errorMessage = String.Empty
    
            If validatedUrls.Contains(CurrentSiteUrl) Then
                isValid = True
            Else
                Dim uriToValidate As Uri = New Uri(CurrentSiteUrl, UriKind.Absolute)
                Dim vsThreadedWaitDialog As IVsThreadedWaitDialog2 = Nothing
    
                Try
                    vsThreadedWaitDialog = ShowProgressDialog("Connect to SharePoint",
                        "Connecting to SharePoint site " + CurrentSiteUrl)
                    isValid = Me.ProjectService.SharePointConnection.ExecuteCommand(Of Uri, Boolean)(
                        Contoso.SharePoint.Commands.CommandIds.ValidateSite, uriToValidate)
                Catch ex As Exception
                    errorMessage = "An error occurred while validating the site. " + ex.Message
                Finally
                    If isValid Then
                        validatedUrls.Add(CurrentSiteUrl)
                    End If
                    If vsThreadedWaitDialog IsNot Nothing Then
                        CloseProgressDialog(vsThreadedWaitDialog)
                    End If
                End Try
            End If
            Return isValid
        End Function
    
        ' Gets the available field types from the SharePoint site. Uses the GetFieldTypes SharePoint command to do this.
        Friend Function GetFieldTypes() As ArrayList
            ' If we have not yet validated this site, do it now.
            Dim errorMessage As String = String.Empty
            If Not ValidateCurrentUrl(errorMessage) Then
                MessageBox.Show(String.Format("Cannot connect to the SharePoint site: {0}. {1}",
                    CurrentSiteUrl, errorMessage), "SharePoint Connection Error")
                Return Nothing
            End If
    
            ' Site is valid, so go ahead and get the available field types.
            Dim siteUri As Uri = New Uri(CurrentSiteUrl, UriKind.Absolute)
            Dim vsThreadedWaitDialog As IVsThreadedWaitDialog2 = ShowProgressDialog(
                "Connect to SharePoint", "Connecting to SharePoint site " + CurrentSiteUrl)
            Dim fieldTypesArray As String() = Me.ProjectService.SharePointConnection.ExecuteCommand(Of Uri, String())(
                Contoso.SharePoint.Commands.CommandIds.GetFieldTypes, siteUri)
    
            If vsThreadedWaitDialog IsNot Nothing Then
                CloseProgressDialog(vsThreadedWaitDialog)
            End If
    
            Return New ArrayList(fieldTypesArray)
        End Function
    
        ' Returns the default column group names in SharePoint.
        Friend Function GetFieldGroups() As List(Of String)
            Dim groups As List(Of String) = New List(Of String)()
            groups.Add("Base Columns")
            groups.Add("Core Contact and Calendar Columns")
            groups.Add("Core Document Columns")
            groups.Add("Core Task and Issue Columns")
            groups.Add("Extended Columns")
            Return groups
        End Function
    #End Region
    
    #Region "Properties shared by the wizard implementation and the wizard UI"
    
        Friend ReadOnly Property ProjectService As ISharePointProjectService
            Get
                If projectServiceValue Is Nothing Then
                    projectServiceValue = GetProjectService()
                End If
                Return projectServiceValue
            End Get
        End Property
    
        Friend Property IsSecondPagePopulated As Boolean
        Friend Property IsSandboxed As Boolean
        Friend Property FieldType As String
        Friend Property FieldGroup As String
        Friend Property FieldName As String
        Friend Property CurrentSiteUrl As String
    #End Region
    
    #Region "Private methods"
    
        Private Function GetLocalHostUrl() As String
            Const HttpScheme As String = "http"
            Dim builder As UriBuilder = New UriBuilder(HttpScheme, Environment.MachineName.ToLowerInvariant())
            Return builder.ToString()
        End Function
    
        Private Function GetProjectService() As ISharePointProjectService
            Dim serviceProvider As ServiceProvider = New ServiceProvider(CType(dteObject, IOleServiceProvider))
            Return CType(serviceProvider.GetService(GetType(ISharePointProjectService)), ISharePointProjectService)
        End Function
    
        Private Function ShowProgressDialog(ByVal caption As String, ByVal message As String) As IVsThreadedWaitDialog2
            Dim oleServiceProvider As IOleServiceProvider = CType(dteObject, IOleServiceProvider)
            Dim dialogFactory As IVsThreadedWaitDialogFactory = CType(New ServiceProvider(oleServiceProvider).GetService(
                GetType(SVsThreadedWaitDialogFactory)), IVsThreadedWaitDialogFactory)
    
            If dialogFactory Is Nothing Then
                Throw New InvalidOperationException("The IVsThreadedWaitDialogFactory object could not be retrieved.")
            End If
    
            Dim vsThreadedWaitDialog As IVsThreadedWaitDialog2 = Nothing
            ErrorHandler.ThrowOnFailure(dialogFactory.CreateInstance(vsThreadedWaitDialog))
            ErrorHandler.ThrowOnFailure(vsThreadedWaitDialog.StartWaitDialog(caption, message,
                Nothing, Nothing, String.Empty, 0, False, True))
            Return vsThreadedWaitDialog
        End Function
    
        Private Sub CloseProgressDialog(ByVal vsThreadedWaitDialog As IVsThreadedWaitDialog2)
            If vsThreadedWaitDialog Is Nothing Then
                Throw New ArgumentNullException("vsThreadedWaitDialog")
            End If
            Dim canceled As Integer
            ErrorHandler.ThrowOnFailure(vsThreadedWaitDialog.EndWaitDialog(canceled))
        End Sub
    #End Region
    End Class
    
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Windows;
    using EnvDTE;
    using Microsoft.VisualStudio.SharePoint;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.Shell;
    using Microsoft.VisualStudio.Shell.Interop;
    using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
    
    namespace ProjectTemplateWizard
    {
        internal class SiteColumnWizardModel
        {
            private DTE dteObject;
            private ISharePointProjectService projectServiceValue;
            private List<string> validatedUrls = new List<string>();
    
            internal SiteColumnWizardModel(DTE dteObject, bool requiresFarmPriveleges)
            {
                this.dteObject = dteObject;
    
                // Initialize default values for wizard choices.
                IsSandboxed = !requiresFarmPriveleges;
                IsSecondPagePopulated = false;
                FieldType = "Text";
                FieldGroup = "Custom Columns";
                FieldName = "My Custom Column";
                CurrentSiteUrl = GetLocalHostUrl();
            }
    
            #region Helper methods used by the wizard UI
    
            // Specifies whether the current site URL is valid. Uses the ValidateSite SharePoint command to do this.
            internal bool ValidateCurrentUrl(out string errorMessage)
            {
                bool isValid = false;
                errorMessage = String.Empty;
    
                if (validatedUrls.Contains(CurrentSiteUrl))
                {
                    isValid = true;
                }
                else
                {
                    Uri uriToValidate = new Uri(CurrentSiteUrl, UriKind.Absolute);
                    IVsThreadedWaitDialog2 vsThreadedWaitDialog = null;
    
                    try
                    {
                        vsThreadedWaitDialog = ShowProgressDialog("Connect to SharePoint",
                            "Connecting to SharePoint site " + CurrentSiteUrl);
                        isValid = this.ProjectService.SharePointConnection.ExecuteCommand<Uri, bool>(
                            Contoso.SharePoint.Commands.CommandIds.ValidateSite, uriToValidate);
                    }
                    catch (Exception ex)
                    {
                        errorMessage = "An error occurred while validating the site. " + ex.Message;
                    }
                    finally
                    {
                        if (isValid)
                        {
                            validatedUrls.Add(CurrentSiteUrl);
                        }
    
                        if (vsThreadedWaitDialog != null)
                        {
                            CloseProgressDialog(vsThreadedWaitDialog);
                        }
                    }
                }
    
                return isValid;
            }
    
            // Gets the available field types from the SharePoint site. Uses the GetFieldTypes SharePoint command to do this.
            internal ArrayList GetFieldTypes()
            {
                // If we have not yet validated this site, do it now.
                string errorMessage;
                if (!ValidateCurrentUrl(out errorMessage))
                {
                    MessageBox.Show(String.Format("Cannot connect to the SharePoint site: {0}. {1}",
                        CurrentSiteUrl, errorMessage), "SharePoint Connection Error");
                    return null;
                }
    
                // Site is valid, so go ahead and get the available field types.
                Uri siteUri = new Uri(CurrentSiteUrl, UriKind.Absolute);
                IVsThreadedWaitDialog2 vsThreadedWaitDialog = ShowProgressDialog(
                    "Connect to SharePoint", "Connecting to SharePoint site " + CurrentSiteUrl);
                string[] fieldTypesArray = this.ProjectService.SharePointConnection.ExecuteCommand<Uri, string[]>(
                        Contoso.SharePoint.Commands.CommandIds.GetFieldTypes, siteUri);
    
                if (vsThreadedWaitDialog != null)
                {
                    CloseProgressDialog(vsThreadedWaitDialog);
                }
    
                return new ArrayList(fieldTypesArray);
            }
    
            // Returns the default column group names in SharePoint.
            internal List<string> GetFieldGroups()
            {
                List<string> groups = new List<string>();
                groups.Add("Base Columns");
                groups.Add("Core Contact and Calendar Columns");
                groups.Add("Core Document Columns");
                groups.Add("Core Task and Issue Columns");
                groups.Add("Extended Columns");
                return groups;
            }
    
            #endregion
    
            #region Properties shared by the wizard implementation and the wizard UI
    
            internal ISharePointProjectService ProjectService
            {
                get
                {
                    if (projectServiceValue == null)
                    {
                        projectServiceValue = GetProjectService();
                    }
                    return projectServiceValue;
                }
            }
    
            internal bool IsSecondPagePopulated { get; set; }
            internal bool IsSandboxed { get; set; }
            internal string FieldType { get; set; }
            internal string FieldGroup { get; set; }
            internal string FieldName { get; set; }
            internal string CurrentSiteUrl { get; set; }
    
            #endregion
    
            #region Private methods
    
            private string GetLocalHostUrl()
            {
                const string HttpScheme = "http";
                UriBuilder builder = new UriBuilder(HttpScheme, Environment.MachineName.ToLowerInvariant());
                return builder.ToString();
            }
    
            private ISharePointProjectService GetProjectService()
            {
                ServiceProvider serviceProvider = new ServiceProvider(dteObject as IOleServiceProvider);
                return serviceProvider.GetService(typeof(ISharePointProjectService)) as ISharePointProjectService;
            }
    
            private IVsThreadedWaitDialog2 ShowProgressDialog(string caption, string message)
            {
                IOleServiceProvider oleServiceProvider = dteObject as IOleServiceProvider;
                IVsThreadedWaitDialogFactory dialogFactory = new ServiceProvider(oleServiceProvider).GetService(
                    typeof(SVsThreadedWaitDialogFactory)) as IVsThreadedWaitDialogFactory;
    
                if (dialogFactory == null)
                {
                    throw new InvalidOperationException("The IVsThreadedWaitDialogFactory object could not be retrieved.");
                }
    
                IVsThreadedWaitDialog2 vsThreadedWaitDialog = null;
                ErrorHandler.ThrowOnFailure(dialogFactory.CreateInstance(out vsThreadedWaitDialog));
                ErrorHandler.ThrowOnFailure(vsThreadedWaitDialog.StartWaitDialog(caption, message,
                     null, null, String.Empty, 0, false, true));
                return vsThreadedWaitDialog;
            }
    
            private void CloseProgressDialog(IVsThreadedWaitDialog2 vsThreadedWaitDialog)
            {
                if (vsThreadedWaitDialog == null)
                {
                    throw new ArgumentNullException("vsThreadedWaitDialog");
                }
    
                int canceled;
                ErrorHandler.ThrowOnFailure(vsThreadedWaitDialog.EndWaitDialog(out canceled));
            }
    
            #endregion
        }
    }
    

Pour créer le gestionnaire de signature de projet

  • Ouvrez le fichier de code ProjectSigningManager, puis remplacez le contenu du fichier entier par le code suivant.

    Imports EnvDTE
    Imports System
    Imports System.IO
    Imports System.Runtime.InteropServices
    
    Friend Class ProjectSigningManager
        Private Const KEY_FILENAME As String = "key.snk"
        Private keyBuffer As Byte()
        Private strongNameGenerated As Boolean = False
    
    #Region "Methods used by the project wizard"
    
        Friend Sub GenerateKeyFile()
            If Not strongNameGenerated Then
                keyBuffer = CreateNewKeyPair()
                strongNameGenerated = True
            End If
        End Sub
    
        Friend Sub AddKeyFile(ByVal project As Project)
            If strongNameGenerated Then
                AddKeyFileToProject(project)
            End If
        End Sub
    #End Region
    
    #Region "Private members"
    
        Private Function CreateNewKeyPair() As Byte()
            Dim buffer As IntPtr = IntPtr.Zero
            Dim bufferSize As UInteger
            Dim keyBuffer As Byte()
    
            Try
                If 0 = NativeMethods.StrongNameKeyGen(IntPtr.Zero, 0, buffer, bufferSize) Then
                    Marshal.ThrowExceptionForHR(NativeMethods.StrongNameErrorInfo())
                End If
                If buffer = IntPtr.Zero Then
                    Throw New InvalidOperationException("Cannot generate the strong name key.")
                End If
    
                ' Copy generated key to managed memory.
                keyBuffer = New Byte(bufferSize) {}
                Marshal.Copy(buffer, keyBuffer, 0, CInt(bufferSize))
            Finally
                ' Free native resources.
                NativeMethods.StrongNameFreeBuffer(buffer)
            End Try
            Return keyBuffer
        End Function
    
        Private Sub AddKeyFileToProject(ByVal project As Project)
    
            ' Save the key to a file.
            If keyBuffer IsNot Nothing Then
                Try
                    Dim destinationDirectory As String = Path.GetDirectoryName(project.FullName)
                    Dim keySavePath As String = Path.Combine(destinationDirectory, KEY_FILENAME)
    
                    File.WriteAllBytes(keySavePath, keyBuffer)
                    project.ProjectItems.AddFromFile(keySavePath)
    
                    ' Add properties in the project to use the key for signing.
                    Dim projProps As EnvDTE.Properties = project.Properties
                    projProps.Item("SignAssembly").Value = True
                    projProps.Item("AssemblyOriginatorKeyFile").Value = KEY_FILENAME
                Catch e As Exception
                    Throw New Exception("Cannot add the strong name key to the project. " & e.Message, e)
                End Try
            End If
        End Sub
    
        Private Class NativeMethods
            <DllImport("mscoree.dll")>
            Friend Shared Function StrongNameFreeBuffer(ByVal pbMemory As IntPtr) As Integer
            End Function
    
            <DllImport("mscoree.dll", CharSet:=CharSet.Unicode, ExactSpelling:=True)>
            Friend Shared Function StrongNameKeyGen(ByVal wszKeyContainer As IntPtr, ByVal dwFlags As UInteger, _
                ByRef KeyBlob As IntPtr, ByRef KeyBlobSize As UInteger) As Integer
            End Function
    
            <DllImport("mscoree.dll", CharSet:=CharSet.Unicode)>
            Friend Shared Function StrongNameErrorInfo() As Integer
            End Function
        End Class
    #End Region
    End Class
    
    using EnvDTE;
    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    
    namespace ProjectTemplateWizard
    {
        internal class ProjectSigningManager
        {
            private const string KEY_FILENAME = "key.snk";
            private byte[] keyBuffer;
            private bool strongNameGenerated = false;
    
            #region Methods used by the project wizard
    
            internal void GenerateKeyFile()
            {
                if (!strongNameGenerated)
                {
                    keyBuffer = CreateNewKeyPair();
                    strongNameGenerated = true;
                }
            }
    
            internal void AddKeyFile(Project project)
            {
                if (strongNameGenerated)
                {
                    AddKeyFileToProject(project);
                }
            }
    
            #endregion
    
            #region Private members
    
            private byte[] CreateNewKeyPair()
            {
                IntPtr buffer = IntPtr.Zero;
                uint bufferSize;
                byte[] keyBuffer;
    
                try
                {
                    if (0 == NativeMethods.StrongNameKeyGen(IntPtr.Zero, 0, out buffer, out bufferSize))
                    {
                        Marshal.ThrowExceptionForHR(NativeMethods.StrongNameErrorInfo());
                    }
    
                    if (buffer == IntPtr.Zero)
                    {
                        throw new InvalidOperationException("Cannot generate the strong name key.");
                    }
    
                    // Copy generated key to managed memory.
                    keyBuffer = new byte[bufferSize];
                    Marshal.Copy(buffer, keyBuffer, 0, (int)bufferSize);
                }
                finally
                {
                    // Free native resources.
                    NativeMethods.StrongNameFreeBuffer(buffer);
                }
    
                return keyBuffer;
            }
    
            private void AddKeyFileToProject(Project project)
            {
                // Save the key to a file.
                if (keyBuffer != null)
                {
                    try
                    {
                        string destinationDirectory = Path.GetDirectoryName(project.FullName);
                        string keySavePath = Path.Combine(destinationDirectory, KEY_FILENAME);
    
                        File.WriteAllBytes(keySavePath, keyBuffer);
                        project.ProjectItems.AddFromFile(keySavePath);
    
                        // Add properties in the project to use the key for signing.
                        EnvDTE.Properties projProps = project.Properties;
                        projProps.Item("SignAssembly").Value = true;
                        projProps.Item("AssemblyOriginatorKeyFile").Value = KEY_FILENAME;
                    }
                    catch (Exception e)
                    {
                        throw new Exception("Cannot add the strong name key to the project. " + e.Message, e);
                    }
                }
            }
    
            private static class NativeMethods
            {
                [DllImport("mscoree.dll")]
                internal extern static int StrongNameFreeBuffer(IntPtr pbMemory);
    
                [DllImport("mscoree.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
                internal static extern int StrongNameKeyGen(IntPtr wszKeyContainer, uint dwFlags, out IntPtr KeyBlob, 
                    out uint KeyBlobSize);
    
                [DllImport("mscoree.dll", CharSet = CharSet.Unicode)]
                internal static extern int StrongNameErrorInfo();
            }
    
            #endregion
        }
    }
    

Création de l'interface utilisateur de l'Assistant

Ajoutez la syntaxe XAML pour définir l'interface utilisateur de la fenêtre de l'Assistant et les deux contrôles utilisateur qui fournissent l'interface utilisateur pour les pages de l'Assistant, puis ajoutez le code pour définir le comportement de la fenêtre et des contrôles utilisateur.L'assistant que vous créez ressemble à l'assistant intégré des projets sharepoint dans Visual Studio.

[!REMARQUE]

Dans les étapes suivantes, Votre projet comportera des erreurs de compilation après avoir ajouté la syntaxe XAML ou le code à votre projet.Ces erreurs disparaîtront lorsque vous ajouterez du code dans les étapes ultérieures.

Pour créer l'interface utilisateur de la fenêtre de l'Assistant

  1. Dans le projet ProjectTemplateWizard, ouvrez le menu contextuel du fichier WizardWindow.xaml, puis choisissez Ouvrir pour ouvrir la fenêtre dans le concepteur.

  2. Dans la vue XAML du concepteur, remplacez le code XAML actuel par le code XAML suivant.Le code XAML définit une interface utilisateur qui comprend un titre, Grid, contenant les pages de l'Assistant et des boutons de navigation dans la partie inférieure de la fenêtre.

    <ui:DialogWindow x:Class="ProjectTemplateWizard.WizardWindow"
                     xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
                     xmlns:ui="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.11.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 Height="28" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="18,0,0,0" 
                       Name="headingLabel" FontWeight="ExtraBold" />
            </Grid>
            <Grid Grid.Row="1" Name="pageGrid" />
            <Rectangle Grid.Row="2" Name="separatorRectangle" Fill="White"  />
            <StackPanel Grid.Row="3" Name="navigationPanel" Orientation="Horizontal">
                <Button Content="&lt; _Previous" Margin="300,0,0,0"  Height="25" Name="previousButton" Width="85" 
                        IsEnabled="False" Click="previousButton_Click" />
                <Button Content="_Next >" Margin="10,0,0,0" Height="25" Name="nextButton" Width="85" Click="nextButton_Click" 
                        IsDefault="True" />
                <Button Content="_Finish" Margin="10,0,0,0" Height="25" Name="finishButton" Width="85" 
                        Click="finishButton_Click" />
                <Button Content="Cancel" Margin="10,0,0,0" Height="25" Name="cancelButton" Width="85" 
                        IsCancel="True" />
            </StackPanel>
        </Grid>
    </ui:DialogWindow>
    

    [!REMARQUE]

    La fenêtre créée dans ce XAML est dérivée de la classe de base d' DialogWindow .Lorsque vous ajoutez une boîte de dialogue de la personnalisés WPF dans Visual Studio, nous recommandons que vous dérivez votre boîte de dialogue de cette classe pour avoir un style cohérent avec d'autres boîtes de dialogue Visual Studio et pour éviter des problèmes de boîte de dialogue modale qui pourraient sinon se produire.Pour plus d’informations, consultez Comment : Créer et gérer des boîtes de dialogue.

  3. Si vous développez un projet Visual Basic, supprimez l'espace de noms d' ProjectTemplateWizard du nom de classe d' WizardWindow dans l'attribut d' x:Class de l'élément d' Window .Cet élément est aligné en premier du XAML.Lorsque vous avez terminé, la première ligne doit ressembler à l'exemple suivant.

    <Window x:Class="WizardWindow"
    
  4. Ouvrez le fichier code-behind correspondant au fichier WizardWindow.xaml.

  5. Remplacez le contenu du fichier, à l'exception de les déclarations d' using en haut du fichier, par le code suivant.

    Public Class WizardWindow
        Private firstPage As Page1
        Private secondPage As Page2
        Private Const firstPageLabel As String = "Specify the site and security level for debugging"
        Private Const secondPageLabel As String = "Configure the site column"
    
        Friend Sub New(ByVal presentationModel As SiteColumnWizardModel)
            InitializeComponent()
            Me.PresentationModel = presentationModel
            firstPage = New Page1(Me)
            secondPage = New Page2(Me)
            secondPage.Visibility = Visibility.Hidden
        End Sub
    
        Friend Property PresentationModel As SiteColumnWizardModel
    
        Private Sub Window_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
            headingLabel.Content = firstPageLabel
            pageGrid.Children.Add(firstPage)
            pageGrid.Children.Add(secondPage)
        End Sub
    
        Private Sub nextButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    
            ' Initialize the second wizard page if this is the first time 
            ' it has been shown with the current site URL.
            If Not PresentationModel.IsSecondPagePopulated Then
    
                If Not ValidateUrl() Then
                    Return
                End If
    
                ' Refresh the UI in the second page.
                secondPage.ClearControls()
                secondPage.PopulateSiteColumnOptions()
    
                ' Do not do this work again until the user changes the site URL.
                PresentationModel.IsSecondPagePopulated = True
            End If
    
            ' Display the second wizard page and update related controls.
            firstPage.Visibility = Visibility.Hidden
            secondPage.Visibility = Visibility.Visible
            previousButton.IsEnabled = True
            nextButton.IsEnabled = False
            nextButton.IsDefault = False
            finishButton.IsDefault = True
            headingLabel.Content = secondPageLabel
        End Sub
    
        ' Display the first wizard page again and update related controls.
        Private Sub previousButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            secondPage.Visibility = Visibility.Hidden
            firstPage.Visibility = Visibility.Visible
            previousButton.IsEnabled = False
            finishButton.IsDefault = False
            nextButton.IsEnabled = True
            nextButton.IsDefault = True
            headingLabel.Content = firstPageLabel
        End Sub
    
        Private Sub finishButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            If ValidateUrl() Then
                DialogResult = True
                Close()
            End If
        End Sub
    
        Private Function ValidateUrl() As Boolean
            Dim errorMessage As String = String.Empty
            If Not PresentationModel.ValidateCurrentUrl(errorMessage) Then
                MessageBox.Show(String.Format("Cannot connect to the SharePoint site: {0}. {1}",
                    PresentationModel.CurrentSiteUrl, errorMessage),
                    "SharePoint Connection Error")
                Return False
            End If
            Return True
        End Function
    End Class
    
    using System;
    using System.Windows;
    using Microsoft.VisualStudio.PlatformUI;
    
    namespace ProjectTemplateWizard
    {
        public partial class WizardWindow : DialogWindow
        {
            private Page1 firstPage;
            private Page2 secondPage;
            private const string firstPageLabel = "Specify the site and security level for debugging";
            private const string secondPageLabel = "Configure the site column";
    
            internal WizardWindow(SiteColumnWizardModel presentationModel)
            {
                InitializeComponent();
                this.PresentationModel = presentationModel;
                firstPage = new Page1(this);
                secondPage = new Page2(this);
                secondPage.Visibility = Visibility.Hidden;
            }
    
            internal SiteColumnWizardModel PresentationModel { get; set; }
    
            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                headingLabel.Content = firstPageLabel;
                pageGrid.Children.Add(firstPage);
                pageGrid.Children.Add(secondPage);
            }
    
            private void nextButton_Click(object sender, RoutedEventArgs e)
            {
                // Initialize the second wizard page if this is the first time 
                // it has been shown with the current site URL.
                if (!PresentationModel.IsSecondPagePopulated)
                {
                    if (!ValidateUrl())
                    {
                        return;
                    }
    
                    // Refresh the UI in the second page.
                    secondPage.ClearControls();
                    secondPage.PopulateSiteColumnOptions();
    
                    // Do not do this work again until the user changes the site URL.
                    PresentationModel.IsSecondPagePopulated = true;
                }
    
                // Display the second wizard page and update related controls.
                firstPage.Visibility = Visibility.Hidden;
                secondPage.Visibility = Visibility.Visible;
                previousButton.IsEnabled = true;
                nextButton.IsEnabled = false;
                finishButton.IsDefault = true;
                headingLabel.Content = secondPageLabel;
            }
    
            // Display the first wizard page again and update related controls.
            private void previousButton_Click(object sender, RoutedEventArgs e)
            {
                secondPage.Visibility = Visibility.Hidden;
                firstPage.Visibility = Visibility.Visible;
                previousButton.IsEnabled = false;
                finishButton.IsDefault = false;
                nextButton.IsEnabled = true;
                nextButton.IsDefault = true;
                headingLabel.Content = firstPageLabel;
            }
    
            private void finishButton_Click(object sender, RoutedEventArgs e)
            {
                if (ValidateUrl())
                {
                    DialogResult = true;
                    Close();
                }
            }
    
            private bool ValidateUrl()
            {
                string errorMessage;
                if (!PresentationModel.ValidateCurrentUrl(out errorMessage))
                {
                    MessageBox.Show(String.Format("Cannot connect to the SharePoint site: {0}. {1}",
                        PresentationModel.CurrentSiteUrl, errorMessage),
                        "SharePoint Connection Error");
                    return false;
                }
                return true;
            }
        }
    }
    

Pour créer la première page de l'interface utilisateur de l'Assistant

  1. Dans le projet ProjectTemplateWizard, ouvrez le menu contextuel du fichier Page1.xaml, puis choisissez Ouvrir pour ouvrir le contrôle utilisateur dans le concepteur.

  2. Dans la vue XAML du concepteur, remplacez le code XAML actuel par le code XAML suivant.Le code XAML définit une interface utilisateur qui comprend une zone de texte où les utilisateurs peuvent entrer l'URL de sites locaux qu'ils souhaitent utiliser pour le débogage.L'interface utilisateur inclut également les cases d'option avec lesquelles les utilisateurs peuvent spécifier si le projet bac à sable (sandbox).

    <UserControl x:Class="ProjectTemplateWizard.Page1"
                 xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="https://schemas.microsoft.com/expression/blend/2008" 
                 mc:Ignorable="d" d:DesignHeight="364" d:DesignWidth="700" Loaded="UserControl_Loaded">
        <Grid Height="364" HorizontalAlignment="Left" Name="page1Grid" Width="700">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="20*" />
                <ColumnDefinition Width="548*" />
                <ColumnDefinition Width="132*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <TextBox Grid.Row="1" Grid.Column="1" Margin="5,0,1,0" Height="23" Name="siteUrlTextBox" 
                     TextChanged="siteUrlTextBox_TextChanged" />
            <Label Grid.Row="0" Grid.Column="1" Margin="0,20,0,0" Name="siteLabel" FontWeight="Bold" 
                   Target="{Binding ElementName=siteUrlTextBox}" 
                   Content="What local _site do you want to use for debugging?" />
            <Button Grid.Row="1" Grid.Column="2" Content="_Validate" Height="25" Name="validateButton" 
                    Width="88" Click="validateButton_Click" HorizontalAlignment="Left" 
                    Margin="5,0,0,0" VerticalAlignment="Top" />
            <Label Grid.Row="2" Grid.Column="1" Margin="0,10,0,0" Content="What is the trust level for this SharePoint solution?" 
                   Name="trustLabel" FontWeight="Bold" />
            <StackPanel Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Orientation="Vertical">
                <RadioButton Content="Deploy as a sand_boxed solution" Margin="5,0,0,0" Name="sandboxedSolutionRadioButton" 
                             FontWeight="Bold" Checked="sandboxedSolutionRadioButton_Checked" />
                <TextBlock TextWrapping="WrapWithOverflow" Margin="20,7,50,0">Clicking this option causes the solution to be 
                           deployed as a Sandboxed solution. Sandboxed solutions can be deployed by the site collection owner 
                           and are run in a secure, monitored process that has limited resource access.</TextBlock>
                <RadioButton Content="Deploy as a _farm solution" Margin="5,7,0,0" Name="farmSolutionRadioButton" FontWeight="Bold" 
                             Checked="farmSolutionRadioButton_Checked" />
                <TextBlock TextWrapping="WrapWithOverflow" Margin="20,7,50,0">Clicking this option means that users must have 
                           SharePoint administrator privileges to run or deploy the solution.</TextBlock>
            </StackPanel>
        </Grid>
    </UserControl>
    
  3. Si vous développez un projet Visual Basic, supprimez l'espace de noms ProjectTemplateWizard du nom de la classe Page1 dans l'attribut x:Class de l'élément UserControl.Cette indication se trouve dans la première ligne du code XAML.Lorsque vous avez terminé, la première ligne doit se présenter comme suit :

    <UserControl x:Class="Page1"
    
  4. Remplacez le contenu du fichier Page1.xaml, à l'exception de les déclarations d' using en haut du fichier, par le code suivant.

    Public Class Page1
        Private mainWindow As WizardWindow
    
        Friend Sub New(ByVal mainWindow As WizardWindow)
            Me.mainWindow = mainWindow
            InitializeComponent()
        End Sub
    
        Private Sub UserControl_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
            If (mainWindow.PresentationModel.IsSandboxed) Then
                sandboxedSolutionRadioButton.IsChecked = True
            Else
                sandboxedSolutionRadioButton.IsEnabled = False
                farmSolutionRadioButton.IsChecked = True
            End If
            siteUrlTextBox.Text = mainWindow.PresentationModel.CurrentSiteUrl
        End Sub
    
        ' Validate that the URL exists on the development computer.
        Private Sub validateButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Dim errorMessage As String = String.Empty
            validateButton.IsEnabled = False
    
            If Not mainWindow.PresentationModel.ValidateCurrentUrl(errorMessage) Then
                MessageBox.Show(String.Format("Cannot connect to the SharePoint site: {0}. {1}",
                    mainWindow.PresentationModel.CurrentSiteUrl, errorMessage),
                    "SharePoint Connection Error")
            Else
                MessageBox.Show("Successfully connected to SharePoint site " +
                    mainWindow.PresentationModel.CurrentSiteUrl, "Connection Successful")
            End If
            validateButton.IsEnabled = True
        End Sub
    
        ' Prevent users from finishing the wizard if the URL is not formatted correctly.
        Private Sub siteUrlTextBox_TextChanged(ByVal sender As Object, ByVal e As TextChangedEventArgs)
            Dim url As String = EnsureTrailingSlash(siteUrlTextBox.Text)
    
            ' Perform some basic error-checking on the URL here.
            If url.Length > 0 AndAlso Uri.IsWellFormedUriString(Uri.EscapeUriString(url), UriKind.Absolute) Then
    
                mainWindow.finishButton.IsEnabled = True
                mainWindow.nextButton.IsEnabled = True
                validateButton.IsEnabled = True
                mainWindow.PresentationModel.CurrentSiteUrl = url
                mainWindow.PresentationModel.IsSecondPagePopulated = False
            Else
                mainWindow.finishButton.IsEnabled = False
                mainWindow.nextButton.IsEnabled = False
                validateButton.IsEnabled = False
            End If
        End Sub
    
        Private Sub sandboxedSolutionRadioButton_Checked(ByVal sender As Object, ByVal e As RoutedEventArgs)
            mainWindow.PresentationModel.IsSandboxed = CBool(sandboxedSolutionRadioButton.IsChecked)
        End Sub
    
        Private Sub farmSolutionRadioButton_Checked(ByVal sender As Object, ByVal e As RoutedEventArgs)
            mainWindow.PresentationModel.IsSandboxed = CBool(sandboxedSolutionRadioButton.IsChecked)
        End Sub
    
        Private Function EnsureTrailingSlash(ByVal url As String)
            If Not String.IsNullOrEmpty(url) AndAlso url(url.Length - 1) <> "/" Then
                url += "/"
            End If
            Return url
        End Function
    End Class
    
    using System;
    using System.Windows;
    using System.Windows.Controls;
    
    namespace ProjectTemplateWizard
    {
        public partial class Page1 : UserControl
        {
            private WizardWindow mainWindow;
    
            internal Page1(WizardWindow mainWindow)
            {
                this.mainWindow = mainWindow;
                InitializeComponent();
            }
    
            private void UserControl_Loaded(object sender, RoutedEventArgs e)
            {
                if (mainWindow.PresentationModel.IsSandboxed)
                {
                    sandboxedSolutionRadioButton.IsChecked = true;
                }
                else
                {
                    sandboxedSolutionRadioButton.IsEnabled = false;
                    farmSolutionRadioButton.IsChecked = true;
                }
    
                siteUrlTextBox.Text = mainWindow.PresentationModel.CurrentSiteUrl;
            }
    
            // Validate that the URL exists on the development computer.
            private void validateButton_Click(object sender, RoutedEventArgs e)
            {
                string errorMessage;
                validateButton.IsEnabled = false;
    
                if (!mainWindow.PresentationModel.ValidateCurrentUrl(out errorMessage))
                {
                    MessageBox.Show(String.Format("Cannot connect to the SharePoint site: {0}. {1}",
                        mainWindow.PresentationModel.CurrentSiteUrl, errorMessage),
                        "SharePoint Connection Error");
                }
                else
                {
                    MessageBox.Show("Successfully connected to SharePoint site " +
                        mainWindow.PresentationModel.CurrentSiteUrl, "Connection Successful");
                }
    
                validateButton.IsEnabled = true;
            }
    
            // Prevent users from finishing the wizard if the URL is not formatted correctly.
            private void siteUrlTextBox_TextChanged(object sender, TextChangedEventArgs e)
            {
                string url = EnsureTrailingSlash(siteUrlTextBox.Text);
    
                // Perform some basic error-checking on the URL here.
                if ((url.Length > 0) && (Uri.IsWellFormedUriString(Uri.EscapeUriString(url), UriKind.Absolute)))
                {
                    mainWindow.finishButton.IsEnabled = true;
                    mainWindow.nextButton.IsEnabled = true;
                    validateButton.IsEnabled = true;
                    mainWindow.PresentationModel.CurrentSiteUrl = url;
                    mainWindow.PresentationModel.IsSecondPagePopulated = false;
                }
                else
                {
                    mainWindow.finishButton.IsEnabled = false;
                    mainWindow.nextButton.IsEnabled = false;
                    validateButton.IsEnabled = false;
                }
            }
    
            private void sandboxedSolutionRadioButton_Checked(object sender, RoutedEventArgs e)
            {
                mainWindow.PresentationModel.IsSandboxed = (bool)sandboxedSolutionRadioButton.IsChecked;
            }
    
            private void farmSolutionRadioButton_Checked(object sender, RoutedEventArgs e)
            {
                mainWindow.PresentationModel.IsSandboxed = (bool)sandboxedSolutionRadioButton.IsChecked;
            }
    
            private string EnsureTrailingSlash(string url)
            {
                if (!String.IsNullOrEmpty(url)
                    && url[url.Length - 1] != '/')
                {
                    url += '/';
                }
                return url;
            }
        }
    }
    

Pour créer la deuxième page de l'Assistant

  1. Dans le projet ProjectTemplateWizard, ouvrez le menu contextuel du fichier Page2.xaml, puis choisissez Ouvrir.

    Le contrôle utilisateur s'affiche dans le concepteur.

  2. En mode XAML, remplacez le code XAML existant par le code XAML suivant.Le code XAML définit une interface utilisateur qui comprend une liste déroulante permettant de sélectionner le type de base de la colonne de site, une zone de liste déroulante pour spécifier un groupe intégré ou personnalisé sous lequel vous pouvez afficher la colonne de site dans la galerie et enfin une zone de texte pour spécifier le nom de la colonne de site.

    <UserControl x:Class="ProjectTemplateWizard.Page2"
                 xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="https://schemas.microsoft.com/expression/blend/2008" 
                 mc:Ignorable="d" d:DesignHeight="364" d:DesignWidth="700" Loaded="UserControl_Loaded">
        <Grid Height="364" HorizontalAlignment="Left" Name="page2Grid" Width="700">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="20*" />
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="450*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <Label Grid.Row="0" Grid.Column="1" Margin="0,20,0,0" Content="_Type:" Name="fieldTypeLabel" 
                   FontWeight="Bold" Target="{Binding ElementName=fieldTypeComboBox}"/>
            <Label Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" Content="_Group:" Name="groupLabel" 
                   FontWeight="Bold" Target="{Binding ElementName=groupComboBox}"/>
            <Label Grid.Row="2" Grid.Column="1" Margin="0,10,0,0" Content="_Name:" Name="nameLabel" 
                   FontWeight="Bold" Target="{Binding ElementName=nameTextBox}"/>
            <ComboBox Grid.Row="0" Grid.Column="2" HorizontalAlignment="Left" Margin="0,20,0,0" Height="23" 
                      Name="fieldTypeComboBox" Width="450" SelectionChanged="fieldTypeComboBox_SelectionChanged" />
            <ComboBox Grid.Row="1" Grid.Column="2" HorizontalAlignment="Left" Margin="0,10,0,0" Height="23" 
                      Name="groupComboBox" Width="450" IsEditable="True"  />
            <TextBox Grid.Row="2" Grid.Column="2" HorizontalAlignment="Left"  Margin="0,10,0,0" Height="23" 
                     Name="nameTextBox" Width="450" TextChanged="nameTextBox_TextChanged" />
        </Grid>
    </UserControl>
    
  3. Si vous développez un projet Visual Basic, supprimez l'espace de noms ProjectTemplateWizard du nom de la classe Page2 dans l'attribut x:Class de l'élément UserControl.Cette indication se trouve dans la première ligne du code XAML.Lorsque vous avez terminé, la première ligne doit se présenter comme suit :

    <UserControl x:Class="Page2"
    
  4. Remplacez le contenu du fichier code-behind correspondant au fichier Page2.xaml, à l'exception de les déclarations d' using en haut du fichier, par le code suivant.

    Public Class Page2
        Private mainWindow As WizardWindow
        Private innerTextBoxForGroupComboBox As TextBox
    
        Friend Sub New(ByVal mainWindow As WizardWindow)
            Me.mainWindow = mainWindow
            InitializeComponent()
        End Sub
    
        Friend Sub ClearControls()
            fieldTypeComboBox.Items.Clear()
            groupComboBox.Items.Clear()
            nameTextBox.Clear()
        End Sub
    
        Friend Sub PopulateSiteColumnOptions()
            ' Add the available field type names to the combo box.
            Dim fieldTypes As System.Collections.ArrayList = mainWindow.PresentationModel.GetFieldTypes()
            If fieldTypes IsNot Nothing Then
                fieldTypes.Sort()
                For Each fieldValue As String In fieldTypes
                    fieldTypeComboBox.Items.Add(fieldValue)
                Next
                fieldTypeComboBox.SelectedIndex = 0
            End If
    
            ' Add the default group names to the combo box.
            Dim fieldGroups As List(Of String) = mainWindow.PresentationModel.GetFieldGroups()
            For Each fieldGroupValue As String In fieldGroups
                groupComboBox.Items.Add(fieldGroupValue)
            Next
            groupComboBox.SelectedIndex = 0
        End Sub
    
        Private Sub UserControl_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Handle the TextChanged event of the underlying TextBox for the ComboBox. This enables us to determine 
            ' 1) when the user selects an item in the list and 2) when they type their own custom group name. 
            ' The ComboBox.SelectionChanged event is not raised when you type in an editable ComboboBox.
            innerTextBoxForGroupComboBox = CType(groupComboBox.Template.FindName(
                "PART_EditableTextBox", groupComboBox), TextBox)
            AddHandler innerTextBoxForGroupComboBox.TextChanged, AddressOf innerTextBoxForGroupComboBox_TextChanged
        End Sub
    
        Private Sub fieldTypeComboBox_SelectionChanged(ByVal sender As Object, ByVal e As SelectionChangedEventArgs)
            mainWindow.PresentationModel.FieldType = CStr(fieldTypeComboBox.SelectedItem)
        End Sub
    
        Private Sub innerTextBoxForGroupComboBox_TextChanged(ByVal sender As Object, ByVal e As TextChangedEventArgs)
            mainWindow.PresentationModel.FieldGroup = groupComboBox.Text
        End Sub
    
        Private Sub nameTextBox_TextChanged(ByVal sender As Object, ByVal e As TextChangedEventArgs)
            mainWindow.PresentationModel.FieldName = nameTextBox.Text
        End Sub
    End Class
    
    using System.Windows;
    using System.Windows.Controls;
    
    namespace ProjectTemplateWizard
    {
        public partial class Page2 : UserControl
        {
            private WizardWindow mainWindow;
            private TextBox innerTextBoxForGroupComboBox;
    
            internal Page2(WizardWindow mainWindow)
            {
                this.mainWindow = mainWindow;
                InitializeComponent();
            }
    
            internal void ClearControls()
            {
                fieldTypeComboBox.Items.Clear();
                groupComboBox.Items.Clear();
                nameTextBox.Clear();
            }
    
            internal void PopulateSiteColumnOptions()
            {
                // Add the available field type names to the combo box.
                System.Collections.ArrayList fieldTypes = mainWindow.PresentationModel.GetFieldTypes();
                if (fieldTypes != null)
                {
                    fieldTypes.Sort();
                    foreach (string fieldValue in fieldTypes)
                    {
                        fieldTypeComboBox.Items.Add(fieldValue);
                    }
    
                    fieldTypeComboBox.SelectedIndex = 0;
                }
    
                // Add the default group names to the combo box.
                System.Collections.Generic.List<string> fieldGroups = mainWindow.PresentationModel.GetFieldGroups();
                foreach (string fieldGroupValue in fieldGroups)
                {
                    groupComboBox.Items.Add(fieldGroupValue);
                }
    
                groupComboBox.SelectedIndex = 0;
            }
    
            private void UserControl_Loaded(object sender, RoutedEventArgs e)
            {
                // Handle the TextChanged event of the underlying TextBox for the ComboBox. This enables us to determine 
                // 1) when the user selects an item in the list and 2) when they type their own custom group name. 
                // The ComboBox.SelectionChanged event is not raised when you type in an editable ComboboBox.
                innerTextBoxForGroupComboBox = groupComboBox.Template.FindName(
                    "PART_EditableTextBox", groupComboBox) as TextBox;
                innerTextBoxForGroupComboBox.TextChanged += innerTextBoxForGroupComboBox_TextChanged;
            }
    
            private void fieldTypeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                mainWindow.PresentationModel.FieldType = (string)fieldTypeComboBox.SelectedItem;
            }
    
            void innerTextBoxForGroupComboBox_TextChanged(object sender, TextChangedEventArgs e)
            {
                mainWindow.PresentationModel.FieldGroup = groupComboBox.Text;
            }
    
            private void nameTextBox_TextChanged(object sender, TextChangedEventArgs e)
            {
                mainWindow.PresentationModel.FieldName = nameTextBox.Text;
            }
        }
    }
    

Implémentation de l'Assistant

Définissez les principales fonctionnalités de l'Assistant en implémentant l'interface IWizard.Cette interface définit les méthodes appelées par Visual Studio lorsque l'Assistant démarre et finit et à certains moments pendant l'exécution de l'Assistant.

Pour implémenter l'Assistant

  1. Dans le projet ProjectTemplateWizard, ouvrez le fichier de code SiteColumnProjectWizard.

  2. Remplacez le contenu entier de ce fichier par le code suivant.

    Imports EnvDTE
    Imports Microsoft.VisualStudio.SharePoint
    Imports Microsoft.VisualStudio.TemplateWizard
    Imports System
    Imports System.Collections.Generic
    
    Public Class SiteColumnProjectWizard
        Implements IWizard
    
        Private wizardUI As WizardWindow
        Private dteObject As DTE
        Private presentationModel As SiteColumnWizardModel
        Private signingManager As ProjectSigningManager
    
        Public Sub New()
            signingManager = New ProjectSigningManager()
        End Sub
    
        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
    
            dteObject = CType(automationObject, DTE)
            presentationModel = New SiteColumnWizardModel(dteObject, False)
    
            If Not presentationModel.ProjectService.IsSharePointInstalled Then
                Dim errorString As String = "A SharePoint server is not installed on this computer. A SharePoint server " &
                    "must be installed to work with SharePoint projects."
                System.Windows.MessageBox.Show(errorString, "SharePoint Not Installed", System.Windows.MessageBoxButton.OK,
                    System.Windows.MessageBoxImage.Error)
                Throw New WizardCancelledException(errorString)
            End If
    
            wizardUI = New WizardWindow(presentationModel)
            Dim dialogCompleted? As Boolean = wizardUI.ShowModal()
    
            If (dialogCompleted = True) Then
                replacementsDictionary.Add("$selectedfieldtype$", presentationModel.FieldType)
                replacementsDictionary.Add("$selectedgrouptype$", presentationModel.FieldGroup)
                replacementsDictionary.Add("$fieldname$", presentationModel.FieldName)
                signingManager.GenerateKeyFile()
            Else
                Throw New WizardCancelledException()
            End If
        End Sub
    
        ' Populate the SiteUrl and IsSandboxedSolution properties in the new project, and add a new 
        ' key.snk file to the project.
        Public Sub ProjectFinishedGenerating(ByVal project As Project) _
            Implements IWizard.ProjectFinishedGenerating
            Dim sharePointProject As ISharePointProject = presentationModel.ProjectService.Convert(Of Project, ISharePointProject)(project)
            sharePointProject.SiteUrl = New Uri(presentationModel.CurrentSiteUrl, UriKind.Absolute)
            sharePointProject.IsSandboxedSolution = presentationModel.IsSandboxed
            signingManager.AddKeyFile(project)
        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 used in this example.
        Public Sub BeforeOpeningFile(ByVal projectItem As ProjectItem) _
            Implements IWizard.BeforeOpeningFile
        End Sub
    
        Public Sub ProjectItemFinishedGenerating(ByVal projectItem As ProjectItem) _
            Implements IWizard.ProjectItemFinishedGenerating
        End Sub
    
        Public Sub RunFinished() Implements IWizard.RunFinished
        End Sub
    End Class
    
    using EnvDTE;
    using Microsoft.VisualStudio.SharePoint;
    using Microsoft.VisualStudio.TemplateWizard;
    using System;
    using System.Collections.Generic;
    
    namespace ProjectTemplateWizard
    {
        public class SiteColumnProjectWizard : IWizard
        {
            private WizardWindow wizardUI;
            private DTE dteObject;
            private SiteColumnWizardModel presentationModel;
            private ProjectSigningManager signingManager;
    
            public SiteColumnProjectWizard()
            {
                signingManager = new ProjectSigningManager();
            }
    
            public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, 
                WizardRunKind runKind, object[] customParams)
            {
                dteObject = automationObject as DTE;
                presentationModel = new SiteColumnWizardModel(dteObject, false);
    
                if (!presentationModel.ProjectService.IsSharePointInstalled)
                {
                    string errorString = "A SharePoint server is not installed on this computer. A SharePoint server " +
                        "must be installed to work with SharePoint projects.";
                    System.Windows.MessageBox.Show(errorString, "SharePoint Not Installed", System.Windows.MessageBoxButton.OK,
                        System.Windows.MessageBoxImage.Error);
                    throw new WizardCancelledException(errorString);
                }
    
                wizardUI = new WizardWindow(presentationModel);
                Nullable<bool> dialogCompleted = wizardUI.ShowModal();
    
                if (dialogCompleted == true)
                {
                    replacementsDictionary.Add("$selectedfieldtype$", presentationModel.FieldType);
                    replacementsDictionary.Add("$selectedgrouptype$", presentationModel.FieldGroup);
                    replacementsDictionary.Add("$fieldname$", presentationModel.FieldName);
                    signingManager.GenerateKeyFile();
                }
                else
                {
                    throw new WizardCancelledException();
                }
            }
    
            // Populate the SiteUrl and IsSandboxedSolution properties in the new project, and add a new 
            // key.snk file to the project.
            public void ProjectFinishedGenerating(Project project)
            {
                ISharePointProject sharePointProject = presentationModel.ProjectService.Convert<Project, ISharePointProject>(project);
                sharePointProject.SiteUrl = new Uri(presentationModel.CurrentSiteUrl, UriKind.Absolute);
                sharePointProject.IsSandboxedSolution = presentationModel.IsSandboxed;
                signingManager.AddKeyFile(project);
            }
    
            // 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 used in this example.
            public void BeforeOpeningFile(ProjectItem projectItem)
            {
            }
    
            public void ProjectItemFinishedGenerating(ProjectItem projectItem)
            {
            }
    
            public void RunFinished()
            {
            }
        }
    }
    

Création de commandes SharePoint

Créez deux commandes personnalisées faisant appel au modèle objet serveur SharePoint.Une commande détermine si l'URL du site que l'utilisateur entre dans l'Assistant est valide.L'autre commande permet d'obtenir tous les types de champ du site SharePoint spécifié afin que les utilisateurs puissent sélectionner celle à utiliser comme base pour la nouvelle colonne de site.

Pour définir les commandes SharePoint

  1. Dans le projet SharePointCommands, ouvrez le fichier de code Commands.

  2. Remplacez le contenu entier de ce fichier par le code suivant.

    Imports Microsoft.SharePoint
    Imports Microsoft.VisualStudio.SharePoint.Commands
    
    Namespace Contoso.SharePoint.Commands
    
        Friend Class Commands
    
            <SharePointCommand(CommandIds.ValidateSite)> _
            Private Function ValidateSite(ByVal context As ISharePointCommandContext, ByVal url As Uri) As Boolean
                Using site As SPSite = New SPSite(url.AbsoluteUri)
                    Dim webUrl As String = DetermineWebUrl(url.AbsolutePath, site.ServerRelativeUrl)
                    If webUrl IsNot Nothing Then
                        Using web As SPWeb = site.OpenWeb(webUrl, True)
                            Return web.Exists
                        End Using
                    End If
                End Using
                Return False
            End Function
    
            ' For simplicity, this command does not check to make sure the provided Uri is valid. 
            ' Use the ValidateSite command to verify that the Uri is valid first.
            <SharePointCommand(CommandIds.GetFieldTypes)> _
            Private Function GetFieldTypes(ByVal context As ISharePointCommandContext, ByVal url As Uri) As String()
                Dim columnDefinitions As List(Of String) = New List(Of String)()
                Using site As SPSite = New SPSite(url.AbsoluteUri)
                    Dim webUrl As String = DetermineWebUrl(url.AbsolutePath, site.ServerRelativeUrl)
                    Using web As SPWeb = site.OpenWeb(webUrl, True)
                        For Each columnDefinition As SPFieldTypeDefinition In web.FieldTypeDefinitionCollection
                            columnDefinitions.Add(columnDefinition.TypeName)
                        Next
                        ' SharePoint commands cannot serialize List<string>, so return an array.
                        Return columnDefinitions.ToArray()
                    End Using
                End Using
            End Function
    
            Private Function DetermineWebUrl(ByVal serverRelativeInputUrl As String, ByVal serverRelativeSiteUrl As String) As String
                ' Make sure both URLs have a trailing slash.
                serverRelativeInputUrl = EnsureTrailingSlash(serverRelativeInputUrl)
                serverRelativeSiteUrl = EnsureTrailingSlash(serverRelativeSiteUrl)
    
                Dim webUrl As String = Nothing
                Dim isSubString As Boolean = serverRelativeInputUrl.StartsWith(serverRelativeSiteUrl, StringComparison.OrdinalIgnoreCase)
    
                If isSubString Then
                    ' The Web URL cannot have escaped characters.
                    webUrl = Uri.UnescapeDataString(serverRelativeInputUrl.Substring(serverRelativeSiteUrl.Length))
                End If
                Return webUrl
            End Function
    
            Private Function EnsureTrailingSlash(ByVal url As String)
                If Not String.IsNullOrEmpty(url) AndAlso url(url.Length - 1) <> "/" Then
                    url += "/"
                End If
                Return url
            End Function
        End Class
    End Namespace
    
    using System;
    using System.Collections.Generic;
    using Microsoft.SharePoint;
    using Microsoft.VisualStudio.SharePoint.Commands;
    
    namespace Contoso.SharePoint.Commands
    {
        internal class Commands
        {
            [SharePointCommand(CommandIds.ValidateSite)]
            private bool ValidateSite(ISharePointCommandContext context, Uri url)
            {
                using (SPSite site = new SPSite(url.AbsoluteUri))
                {
                    string webUrl = DetermineWebUrl(url.AbsolutePath, site.ServerRelativeUrl);
                    if (webUrl != null)
                    {
                        using (SPWeb web = site.OpenWeb(webUrl, true))
                        {
                            return web.Exists;
                        }
                    }
                }
    
                return false;
            }
    
            // For simplicity, this command does not check to make sure the provided Uri is valid. 
            // Use the ValidateSite command to verify that the Uri is valid first.
            [SharePointCommand(CommandIds.GetFieldTypes)]
            private string[] GetFieldTypes(ISharePointCommandContext context, Uri url)
            {
                List<string> columnDefinitions = new List<string>();
                using (SPSite site = new SPSite(url.AbsoluteUri))
                {
                    string webUrl = DetermineWebUrl(url.AbsolutePath, site.ServerRelativeUrl);
                    using (SPWeb web = site.OpenWeb(webUrl, true))
                    {
                        foreach (SPFieldTypeDefinition columnDefinition in web.FieldTypeDefinitionCollection)
                        {
                            columnDefinitions.Add(columnDefinition.TypeName);
                        }
    
                        // SharePoint commands cannot serialize List<string>, so return an array.
                        return columnDefinitions.ToArray();
                    }
                }
            }
    
            private string DetermineWebUrl(string serverRelativeInputUrl, string serverRelativeSiteUrl)
            {
                // Make sure both URLs have a trailing slash.
                serverRelativeInputUrl = EnsureTrailingSlash(serverRelativeInputUrl);
                serverRelativeSiteUrl = EnsureTrailingSlash(serverRelativeSiteUrl);
    
                string webUrl = null;
                bool isSubString = serverRelativeInputUrl.StartsWith(serverRelativeSiteUrl, StringComparison.OrdinalIgnoreCase);
    
                if (isSubString)
                {
                    // The Web URL cannot have escaped characters.
                    webUrl = Uri.UnescapeDataString(serverRelativeInputUrl.Substring(serverRelativeSiteUrl.Length));
                }
    
                return webUrl;
            }
    
            private string EnsureTrailingSlash(string url)
            {
                if (!String.IsNullOrEmpty(url)
                    && url[url.Length - 1] != '/')
                {
                    url += '/';
                }
                return url;
            }
        }
    }
    

Point de contrôle

À ce stade de la procédure, l'intégralité du code de l'Assistant fait désormais partie du projet.Générez le projet afin de garantir sa compilation sans erreur.

Pour générer votre projet

  • Dans la barre de menus, sélectionnez Générer, Générer la solution.

Suppression du fichier key.snk du modèle de projet

Dans Procédure pas à pas : création d'un élément de projet de colonnes de sites avec un modèle de projet, première partie, le modèle de projet que vous avez créé contient un fichier key.snk utilisé pour signer chaque instance du projet Colonne de site.Ce fichier key.snk n'est plus nécessaire parce que l'Assistant génère désormais un nouveau fichier key.snk pour chaque projet.Supprimez le fichier key.snk du modèle de projet et supprimez les références à ce fichier.

Pour supprimer le fichier key.snk du modèle de projet

  1. Dans Explorateur de solutions, sous le nœud SiteColumnProjectTemplate , ouvrez le menu contextuel du fichier key.snk , puis choisissez Supprimer.

  2. Dans la boîte de dialogue de confirmation qui apparaît, cliquez sur le bouton OK .

  3. Sous le nœud SiteColumnProjectTemplate , ouvrez le fichier SiteColumnProjectTemplate.vstemplate, puis supprimez l'élément suivant de lui.

    <ProjectItem ReplaceParameters="false" TargetFileName="key.snk">key.snk</ProjectItem>
    
  4. Enregistrez et fermez le fichier.

  5. Sous le nœud SiteColumnProjectTemplate , ouvrez le fichier ProjectTemplate.csproj ou ProjectTemplate.vbproj, puis supprimez l'élément suivant de PropertyGroup de lui.

    <PropertyGroup>
      <SignAssembly>true</SignAssembly>
      <AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
    </PropertyGroup>
    
  6. Supprimez l'élément None suivant.

    <None Include="key.snk" />
    
  7. Enregistrez et fermez le fichier.

Association de l'Assistant au modèle de projet

Maintenant que vous avez implémenté l'Assistant, vous devez l'associer au modèle de projet Colonne de site.Cette opération se déroule en trois étapes :

  1. Signature de l'assembly de l'Assistant avec un nom fort.

  2. Obtention du jeton de clé publique correspondant à l'assembly de l'Assistant.

  3. Ajoutez une référence à l'assembly de l'Assistant dans le fichier .vstemplate du modèle de projet Colonne de site.

Pour signer l'assembly de l'Assistant avec un nom fort

  1. Dans Explorateur de solutions, ouvrez le menu contextuel du projet ProjectTemplateWizard , puis choisissez Propriétés.

  2. Sous l'onglet Signature, activez la case à cocher Signer l'assembly.

  3. Dans la liste choisissez un fichier de clé de nom fort , choisissez <New...>.

  4. Dans la boîte de dialogue créez la clé de nom fort , entrez un nom pour le nouveau fichier de clé, désactivez la case à cocher protégez mon fichier de clé avec un mot de passe , puis choisissez le bouton OK .

  5. Ouvrez le menu contextuel du projet ProjectTemplateWizard , puis choisissez Générer pour créer le fichier ProjectTemplateWizard.dll de.

Pour obtenir le jeton de clé publique correspondant à l'assembly de l'Assistant

  1. Dans Menu démarrer, choisissez Tous les programmes, choisissez Microsoft Visual Studio 2012, choisissez Visual Studio Tools, puis choisissez invite de commandes de développeur pour VS2012.

    Une fenêtre d'invite de commandes de Visual Studio s'ouvre.

  2. Exécutez la commande suivante, en remplaçant PathToWizardAssembly par le chemin d'accès complet à l'assembly ProjectTemplateWizard.dll créé à partir de pour le projet ProjectTemplateWizard sur votre ordinateur de développement :

    sn.exe -T PathToWizardAssembly
    

    Le jeton de clé publique correspondant à l'assembly ProjectTemplateWizard.dll est écrit dans la fenêtre Invite de commandes de Visual Studio.

  3. Ne fermez pas la fenêtre Invite de commandes de Visual Studio.Vous aurez besoin du jeton de clé publique pour la procédure suivante.

Pour ajouter une référence à l'assembly de l'Assistant dans le fichier .vstemplate

  1. Dans l'Explorateur de solutions, développez le nœud du projet SiteColumnProjectTemplate et ouvrez le fichier SiteColumnProjectTemplate.vstemplate.

  2. À l'approche de la fin du fichier, ajoutez l'élément suivant WizardExtension entre les balises </TemplateContent> et </VSTemplate>.Remplacez la valeur de votre jeton de l'attribut PublicKeyToken par le jeton de clé publique que vous avez obtenu dans la procédure précédente.

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

    Pour plus d'informations sur l'élément WizardExtension, consultez WizardExtension, élément (modèles Visual Studio).

  3. Enregistrez et fermez le fichier.

Ajout de paramètres remplaçables au fichier Elements.xml du modèle de projet

Ajoutez plusieurs paramètres remplaçables au fichier Elements.xml du projet SiteColumnProjectTemplate.Ces paramètres sont initialisés dans la méthode RunStarted de la classe SiteColumnProjectWizard que vous avez définie précédemment.Lorsqu'un utilisateur crée un projet Colonne de site, Visual Studio remplace automatiquement ces paramètres dans le fichier Elements.xml du nouvel élément de projet par les valeurs qui ont été spécifiées dans l'Assistant.

Un paramètre remplaçable est un jeton qui commence et se termine par le signe dollar ($).Vous pouvez non seulement définir vos propres paramètres remplaçables, mais également utiliser des paramètres intégrés qui sont définis et initialisés par le système de projet SharePoint.Pour plus d’informations, consultez Paramètres remplaçables.

Pour ajouter des paramètres remplaçables au fichier Elements.xml

  1. Dans le projet SiteColumnProjectTemplate, remplacez le contenu du fichier Elements.xml par le code XML suivant.

    <?xml version="1.0" encoding="utf-8"?>
    <Elements xmlns="https://schemas.microsoft.com/sharepoint/">
      <Field ID="{$guid5$}" 
             Name="$fieldname$" 
             DisplayName="$fieldname$" 
             Type="$selectedfieldtype$" 
             Group="$selectedgrouptype$">
      </Field>
    </Elements>
    

    Dans le nouveau code XML, les paramètres remplaçables se substituent aux valeurs des attributs Name, DisplayName, Type et Group.

  2. Enregistrez et fermez le fichier.

Ajout de l'Assistant au package VSIX

Pour déployer l'Assistant avec le package VSIX qui contient le modèle du projet Colonne de site, ajoutez des références au projet d'Assistant et au projet de commandes SharePoint dans le fichier source.extension.vsixmanifest du projet VSIX.

Pour ajouter l'Assistant au package VSIX

  1. Dans Explorateur de solutions, dans le projet SiteColumnProjectItem , ouvrez le menu contextuel du fichier source.extension.vsixmanifest , puis choisissez Ouvrir.

    Visual Studio ouvre le fichier dans l'éditeur de manifeste.

  2. Sous l'onglet Composants de l'éditeur, choisissez le bouton Nouveau .

    La boîte de dialogue ajoutez le nouveau ressource s'ouvre.

  3. Dans la liste Type , choisissez Microsoft.VisualStudio.Assembly.

  4. Dans la liste Source , choisissez un projet dans la solution actuelle.

  5. Dans la liste Projet , choisissez ProjectTemplateWizard, puis choisissez le bouton OK .

  6. Sous l'onglet Composants de l'éditeur, choisissez le bouton Nouveau de nouveau.

    La boîte de dialogue ajoutez le nouveau ressource s'ouvre.

  7. Dans la liste Type , entrez SharePoint.Commands.v4.

  8. Dans la liste Source , choisissez un projet dans la solution actuelle.

  9. Dans la liste Projet , sélectionnez le projet SharePointCommands , puis choisissez le bouton OK .

  10. Dans la barre de menus, sélectionnez Générer, Générer la solution, puis vérifiez que la solution est générée sans erreurs.

Test de l'Assistant

Vous êtes maintenant prêt à tester l'Assistant.Commencez à déboguer la solution SiteColumnProjectItem dans l'instance expérimentale de Visual Studio.Ensuite, testez l'Assistant du projet Colonne du site dans l'instance expérimentale de Visual Studio.Enfin, générez et exécutez le projet pour vous assurer que la colonne de site fonctionne comme prévu.

Pour commencer à déboguer la solution

  1. Redémarrez Visual Studio avec les informations d'identification d'administration, puis ouvrez la solution SiteColumnProjectItem.

  2. Dans le projet ProjectTemplateWizard, ouvrez le fichier de code SiteColumnProjectWizard, puis ajoutez un point d'arrêt sur la première ligne de code dans la méthode d' RunStarted .

  3. Dans la barre de menus, sélectionnez Déboguer, Exceptions.

  4. Dans la boîte de dialogue Exceptions , assurez -vous que les cases à cocher Levé et utilisateur non pris en charge pour Exceptions du common langage runtime sont supprimées, puis choisissez le bouton OK .

  5. Commencez à déboguer en choisissant la clé F5 ou, dans la barre de menus, choisissant Déboguer, Démarrer le débogage.

    Visual Studio installe l'extension sous %UserProfile%\AppData\Local\Microsoft\VisualStudio\11.0Exp\Extensions\Contoso\Site Column\1.0 and starts an experimental instance of Visual Studio.Vous testerez l'élément de projet dans cette instance de Visual Studio.

Pour tester l'Assistant dans Visual Studio

  1. Dans l'instance expérimentale de Visual Studio, dans le menu, choisissez Fichier, Nouveau, Projet.

  2. Développez le nœud Visual C# ou le nœud Visual Basic (selon le langage qui pris en charge par votre modèle de projet), développez le nœud SharePoint , puis sélectionnez le nœud 2010 .

  3. Dans la liste des modèles de projet, choisissez Recherchez la colonne, nommez le projet SiteColumnWizardTest, puis choisissez le bouton OK .

  4. Assurez-vous que le code dans l'autre instance de Visual Studio s'arrête au niveau du point d'arrêt que vous avez défini précédemment dans la méthode RunStarted.

  5. Continuez à déboguer le projet en sélectionnant la clé F5 ou, dans la barre de menus, choisissant Déboguer, Continuer.

  6. Dans Assistant personnalisation de SharePoint, entrez l'URL du site que vous souhaitez utiliser pour le débogage, puis choisissez le bouton Suivant .

  7. Dans la deuxième page de l'Assistant Personnalisation de SharePoint, effectuez les sélections suivantes :

    • Dans la liste Type , choisissez Boolean.

    • Dans la liste Groupe , choisissez colonnes oui/non personnalisées.

    • Dans la zone Nom , entrez ma colonne oui/non, puis choisissez le bouton Terminer .

    Dans Explorateur de solutions, un nouveau projet s'affiche et contient un élément de projet nommé Field1, et Visual Studio ouvre le fichier Elements.xml du projet dans l'éditeur.

  8. Vérifiez que le fichier Elements.xml contient les valeurs que vous avez spécifiées dans l'Assistant.

Pour tester la colonne de site dans SharePoint

  1. Dans l'instance expérimentale de Visual Studio, choisissez la touche F5.

    La colonne de site est empaquetée et déployée sur le site SharePoint que la propriété Recherchez l'URL du projet spécifie.Le navigateur web s'ouvre à la page par défaut de ce site.

    [!REMARQUE]

    Si la boîte de dialogue Débogage de script est désactivé s'affiche, cliquez sur le bouton oui pour continuer à déboguer le projet.

  2. Dans le menu actions de site , choisissez Paramètres de site.

  3. Sur la page paramètres du site, sous galeries, cliquez sur le lien colonnes de site .

  4. Dans la liste des colonnes de site, vérifiez qu'un groupe colonnes oui/non personnalisées contient une colonne nommée ma colonne oui/non, puis ferme le navigateur web.

Nettoyage de l'ordinateur de développement

Une fois le test de l'élément de projet terminé, supprimez le modèle de projet de l'instance expérimentale de Visual Studio.

Pour nettoyer l'ordinateur de développement

  1. Dans l'instance expérimentale de Visual Studio, dans le menu, choisissez Outils, Extensions et mises à jour.

    La boîte de dialogue Extensions et mises à jour s'ouvre.

  2. Dans la liste d'extensions, choisissez Recherchez la colonne, puis choisissez le bouton Désinstaller .

  3. Dans la boîte de dialogue qui s'affiche, cliquez sur le bouton oui pour confirmer que vous voulez désinstaller l'extension, puis choisissez le bouton Redémarrez maintenant pour terminer la désinstallation.

  4. Fermez l'instance expérimentale de Visual Studio et l'instance dans laquelle la solution élémentprojetactionpersonnalisée est ouverte.

    Pour plus d'informations sur le déploiement d'extensions d' Visual Studio , consultez Déploiement d'une extension Visual Studio.

Voir aussi

Tâches

Procédure pas à pas : création d'un élément de projet de colonnes de sites avec un modèle de projet, première partie

Comment : utiliser des Assistants avec des modèles de projet

Référence

Référence du schéma de modèle Visual Studio

IWizard

Concepts

Définition de types d'éléments de projet SharePoint personnalisés

Création de modèles d'élément et de modèles de projet pour les éléments de projet SharePoint