Condividi tramite


Procedura dettagliata: creazione di un elemento di progetto Colonna del sito con un modello di progetto, parte 2

Dopo avere definito un tipo di elemento di progetto SharePoint personalizzato e averlo associato a un modello di progetto in Visual Studio, è anche possibile fornire una procedura guidata per il modello.È possibile utilizzare la procedura guidata per raccogliere informazioni dagli utenti quando utilizzano il modello per creare un nuovo progetto contenente l'elemento di progetto.Le informazioni raccolte possono essere utilizzate per inizializzare l'elemento di progetto.

In questa procedura dettagliata verrà aggiunta una procedura guidata al modello di progetto Site Column illustrato in Procedura dettagliata: creazione di un elemento di progetto Colonna del sito con un modello di progetto, parte 1.Quando un utente crea un progetto Site Column, tramite la procedura guidata vengono raccolte informazioni sulla colonna del sito (ad esempio il tipo di base e il gruppo) e queste informazioni vengono aggiunte al file Elements.xml nel nuovo progetto.

In questa procedura dettagliata vengono illustrate le attività seguenti:

  • Creazione di una procedura guidata per un tipo di elemento di progetto SharePoint personalizzato associato a un modello di progetto.

  • La definizione dell'interfaccia utente della procedura guidata personalizzata simile a quella delle procedure guidate predefinite per progetti SharePoint in Visual Studio.

  • Creazione di due comandi di SharePoint utilizzati per una chiamata nel sito di SharePoint locale durante l'esecuzione della procedura guidata.I comandi di SharePoint sono metodi che possono essere utilizzati dalle estensioni di Visual Studio per chiamare le API nel modello a oggetti del server SharePoint.Per ulteriori informazioni, vedere Chiamate ai modelli a oggetti di SharePoint.

  • Utilizzo di parametri sostituibili per inizializzare i file di progetto SharePoint con i dati raccolti nella procedura guidata.

  • Creazione di un nuovo file con estensione snk in ogni nuova istanza di progetto Site Column.Questo file viene utilizzato per firmare l'output del progetto in modo che l'assembly della soluzione SharePoint possa essere distribuito nella Global Assembly Cache.

  • Debug e test della procedura guidata.

[!NOTA]

È possibile scaricare un esempio che contiene i progetti completati, il codice e altri file di questa procedura dettagliata all'indirizzo seguente: https://go.microsoft.com/fwlink/?LinkId=191369.

Prerequisiti

Per eseguire questa procedura dettagliata, è prima necessario creare la soluzione SiteColumnProjectItem completando quanto descritto in Procedura dettagliata: creazione di un elemento di progetto Colonna del sito con un modello di progetto, parte 1.

Per completare la procedura dettagliata, nel computer di sviluppo devono inoltre essere disponibili i componenti seguenti:

Per completare la procedura dettagliata è consigliabile conoscere i concetti riportati di seguito:

Informazioni sui componenti della procedura guidata

La procedura guidata dimostrata in questa procedura dettagliata contiene diversi componenti.Tali componenti sono descritti nella tabella seguente.

Componente

Descrizione

Implementazione della procedura guidata

Si tratta di una classe, denominata SiteColumnProjectWizard, che implementa l'interfaccia IWizard.Questa interfaccia definisce i metodi chiamati da Visual Studio all'avvio e al termine della procedura guidata e in determinati momenti durante l'esecuzione.

Interfaccia utente della creazione guidata

Si tratta di una finestra basata su WPF, denominata WizardWindow.Questa finestra comprende due controlli utente, denominati Page1 e Page2.Tali controlli utente rappresentano le due pagine della procedura guidata.

In questa procedura dettagliata, il metodo RunStarted dell'implementazione della procedura guidata ne visualizza l'interfaccia utente.

Modello dati della procedura guidata

Si tratta di una classe intermedia, denominata SiteColumnWizardModel, che fornisce un livello tra l'interfaccia utente e l'implementazione della procedura guidata.Questo esempio utilizza tale classe per consentire la separazione dell'implementazione e dell'interfaccia utente; la classe non è un componente richiesto di tutte le procedure guidate.

In questa procedura dettagliata, l'implementazione della procedura guidata passa un oggetto SiteColumnWizardModel alla finestra della procedura guidata quando viene visualizzata la relativa interfaccia utente.Nell'interfaccia utente della procedura guidata vengono utilizzati i metodi di questo oggetto per salvare i valori dei controlli nell'interfaccia utente e per effettuare operazioni quali la verifica della validità dell'URL del sito di input.Al termine della proceduta guidata da parte dell'utente, l'implementazione della procedura utilizza l'oggetto SiteColumnWizardModel per determinare lo stato finale dell'interfaccia utente.

Responsabile firmatario del progetto

Si tratta di una classe di supporto, denominata ProjectSigningManager, utilizzata dall'implementazione della procedura guidata per creare un nuovo file key.snk in ciascuna nuova istanza del progetto.

Comandi di SharePoint

Si tratta dei metodi utilizzati dal modello dati della procedura guidata per effettuare chiamate nel sito di SharePoint locale durante l'esecuzione della procedura guidata.Poiché i comandi di SharePoint devono essere destinati a .NET Framework 3.5, questi comandi vengono implementati in un assembly diverso dal resto del codice della procedura guidata.

Creazione dei progetti

Per completare questa procedura dettagliata, è necessario aggiungere diversi progetti alla soluzione SiteColumnProjectItem creata in Procedura dettagliata: creazione di un elemento di progetto Colonna del sito con un modello di progetto, parte 1:

  • Un progetto WPF.È quindi necessario implementare l'interfaccia IWizard e definire l'interfaccia utente della procedura guidata in questo progetto.

  • Un progetto Libreria di classi che definisce i comandi di SharePoint.Questo progetto deve essere destinato a .NET Framework 3.5.

Iniziare la procedura dettagliata creando i progetti.

Per creare il progetto WPF

  1. In Visual Studio, aprire la soluzione SiteColumnProjectItem.

  2. In Esplora soluzioni, aprire il menu di scelta rapida del nodo della soluzione SiteColumnProjectItem, scegliere Aggiungiquindi scegliere Nuovo progetto.

    [!NOTA]

    Nei progetti di Visual Basic il nodo della soluzione viene visualizzato solo quando la casella di controllo Mostra sempre soluzione è selezionata in General, Projects and Solutions, Options Dialog Box.

  3. Nella parte superiore della finestra di dialogo Aggiungi nuovo progetto, assicurarsi che .NET Framework 4.5 sia selezionato nell'elenco delle versioni di.NET Framework.

  4. Espandere il nodo Visual C# o il nodo Visual Basic e selezionare il nodo Finestre.

  5. Nell'elenco di modelli di progetto, scegliere Libreria di controlli utente WPF, denominare il progetto ProjectTemplateWizardquindi scegliere il pulsante OK.

    Visual Studio aggiunge il progetto ProjectTemplateWizard alla soluzione e apre il file di impostazione predefinita UserControl1.xaml.

  6. Eliminare il file UserControl1.xaml dal progetto.

Per creare il progetto di comandi di SharePoint

  1. In Esplora soluzioni, aprire il menu di scelta rapida del nodo della soluzione SiteColumnProjectItem, scegliere Aggiungiquindi scegliere Nuovo progetto.

  2. Nella parte superiore della finestra di dialogo Aggiungi nuovo progetto, scegliere .NET Framework 3.5 nell'elenco delle versioni di.NET Framework.

  3. Espandere il nodo Visual C# o il nodo Visual Basic quindi selezionare il nodo Finestre.

  4. Scegliere il modello di progetto Libreria di classi, denominare il progetto SharePointCommandsquindi scegliere il pulsante OK.

    Visual Studio aggiunge il progetto SharePointCommands alla soluzione e apre il file di codice predefinito Class1.

  5. Eliminare il file di codice Class1 dal progetto.

Configurazione dei progetti

Prima di creare la procedura guidata, è necessario aggiungere alcuni file di codice e riferimenti ai progetti.

Per configurare il progetto di procedura guidata

  1. In Esplora soluzioni, aprire il menu di scelta rapida del nodo del progetto ProjectTemplateWizard quindi scegliere Proprietà.

  2. In Progettazione progetti, scegliere la scheda Application per un progetto visual C# o la scheda Compilazione per un progetto di Visual Basic.

  3. Assicurarsi che il framework di destinazione viene impostato su .NET Framework 4,5, non .NET Framework 4,5 Client Profile.

    Per ulteriori informazioni, vedere Procedura: destinare una versione di .NET Framework.

  4. Aprire il menu di scelta rapida del progetto ProjectTemplateWizard, scegliere Aggiungiquindi scegliere Nuovo elemento.

  5. Selezionare l'elemento Finestra (WPF), denominare l'elemento WizardWindowquindi scegliere il pulsante Aggiungi.

  6. Aggiungere due elementi Controllo utente (WPF) al progetto e denominarlo Page1 e Page2.

  7. Aggiungere quattro file di codice al progetto e assegnare loro i nomi seguenti:

    • SiteColumnProjectWizard

    • SiteColumnWizardModel

    • ProjectSigningManager

    • CommandIds

  8. Aprire il menu di scelta rapida del nodo del progetto ProjectTemplateWizard quindi scegliere Aggiungi riferimento.

  9. Espandere il nodo Assembly, selezionare il nodo Estensioni quindi selezionare le caselle di controllo accanto agli assembly seguenti:

    • 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. Scegliere il pulsante OK per aggiungere assembly al progetto.

  11. In Esplora soluzioni, nella cartella Riferimenti per il progetto ProjectTemplateWizard, scegliere EnvDTE.

    [!NOTA]

    Nei progetti di Visual Basic la cartella Riferimenti viene visualizzata solo quando la casella di controllo Mostra sempre soluzione è selezionata in General, Projects and Solutions, Options Dialog Box.

  12. Nella finestra Proprietà, modificare il valore della proprietà Incorpora tipi di interoperabilità a False.

  13. Se si sviluppa un progetto di Visual Basic., importare lo spazio dei nomi ProjectTemplateWizard nel progetto utilizzando Progettazione progetti.

    Per ulteriori informazioni, vedere Procedura: aggiungere o rimuovere spazi dei nomi importati (Visual Basic).

Per configurare il progetto SharePointCommands

  1. In Esplora soluzioni, selezionare il nodo del progetto SharePointCommands.

  2. Sulla barra dei menu, scegliere Project, Aggiungi elemento esistente.

  3. Nella finestra di dialogo Aggiungi elemento esistente, individuare la cartella che contiene file di codice per il progetto ProjectTemplateWizard quindi il file di codice CommandIds.

  4. Scegliere la freccia accanto al pulsante Aggiungi quindi scegliere l'opzione Aggiungi come collegamento nel menu visualizzato.

    Visual Studio aggiunge il file di codice al progetto SharePointCommands come collegamento.Il file di codice si trova nel progetto ProjectTemplateWizard, ma il codice nei file è compilato anche nel progetto SharePointCommands.

  5. Nel progetto SharePointCommands, aggiungere un altro file di codice denominato Commands.

  6. Selezionare il progetto SharePointCommands quindi, nella barra dei menu, scegliere Project, Aggiungi riferimento.

  7. Espandere il nodo Assembly, selezionare il nodo Estensioni quindi selezionare le caselle di controllo accanto agli assembly seguenti:

    • Microsoft.SharePoint

    • Microsoft.VisualStudio.SharePoint.Commands

  8. Scegliere il pulsante OK per aggiungere assembly al progetto.

Creazione del modello di procedura guidata, del responsabile firmatario e degli ID per i comandi di SharePoint

Aggiungere il codice al progetto ProjectTemplateWizard per implementare i componenti seguenti nell'esempio:

  • ID per i comandi di SharePoint.Queste stringhe che identificano i comandi di SharePoint che la procedura guidata.Più avanti in questa procedura dettagliata, si aggiungerà codice al progetto SharePointCommands per implementare i controlli.

  • Modello dati della procedura guidata.

  • Responsabile firmatario del progetto.

Per ulteriori informazioni su questi componenti, vedere Informazioni sui componenti della procedura guidata.

Per definire gli ID per i comandi di SharePoint

  • Nel progetto ProjectTemplateWizard, aprire il file di codice CommandIds quindi sostituire l'intero contenuto del file con il codice seguente.

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

Per creare il modello di procedura guidata

  • Aprire il file di codice SiteColumnWizardModel e sostituire l'intero contenuto del file con il codice seguente.

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

Per creare il responsabile firmatario del progetto

  • Aprire il file di codice ProjectSigningManager quindi sostituire l'intero contenuto del file con il codice seguente.

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

Creazione dell'interfaccia utente della procedura guidata

Aggiungere contenuto XAML per definire l'interfaccia utente della finestra della procedura guidata e i due controlli utente che forniscono l'interfaccia utente per le pagine della procedura guidata, quindi aggiungere codice per definire il comportamento della finestra e dei controlli utente.La procedura guidata creata è simile a quella predefinita per i progetti SharePoint in Visual Studio.

[!NOTA]

Nei passaggi seguenti il progetto includerà degli errori di compilazione dopo l'aggiunta di contenuto XAML o di codice al progetto.che scompariranno quando si aggiunge codice nei passaggi successivi.

Per creare l'interfaccia utente della finestra della procedura guidata

  1. Nel progetto ProjectTemplateWizard, aprire il menu di scelta rapida per il file WizardWindow.xaml quindi scegliere Apri per aprire la finestra nella finestra di progettazione.

  2. Nella visualizzazione XAML della finestra di progettazione sostituire il codice XAML corrente con quello riportato di seguito.Il codice XAML definisce un'interfaccia utente che include un'intestazione, un Grid contenente le pagine della procedura guidata e i pulsanti di navigazione nella parte inferiore della finestra.

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

    [!NOTA]

    La finestra creata in questo codice XAML viene derivata dalla classe base DialogWindow.Quando si aggiunge una finestra di dialogo WPF personalizzata a Visual Studio, è consigliabile deriva la finestra di dialogo da questa classe per far sì che lo stile coerente con altre finestre di dialogo di Visual Studio e per evitare problemi delle finestre di dialogo modali che possono verificarsi in caso contrario.Per ulteriori informazioni, vedere Procedura: creare e gestire le finestre di dialogo.

  3. Se si sviluppa un progetto di Visual Basic., rimuovere lo spazio dei nomi ProjectTemplateWizard il nome della classe WizardWindow nell'attributo x:Class di elemento Window.Questo elemento è la prima riga del codice XAML.Al termine, la prima riga dovrebbe essere analogo al seguente.

    <Window x:Class="WizardWindow"
    
  4. Aprire il file code-behind per il file WizardWindow.xaml.

  5. Sostituire il contenuto di questo file, fatta eccezione per le dichiarazioni usinginizio del file, con il codice seguente.

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

Per creare l'interfaccia utente della prima pagina della procedura guidata

  1. Nel progetto ProjectTemplateWizard, aprire il menu di scelta rapida per il file Page1.xaml quindi scegliere Apri per aprire il controllo utente nella finestra di progettazione.

  2. Nella visualizzazione XAML della finestra di progettazione sostituire il codice XAML corrente con quello riportato di seguito.Il codice XAML definisce un'interfaccia utente che include una casella di testo in cui gli utenti possono immettere l'url dei siti locali da utilizzare per il debug.L'interfaccia utente sono inoltre inclusi i pulsanti di opzione con cui gli utenti possono specificare se il progetto viene creato mediante 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. Se si sviluppa un progetto di Visual Basic, rimuovere lo spazio dei nomi ProjectTemplateWizard dal nome della classe Page1 nell'attributo x:Class dell'elemento UserControl.Lo spazio dei nomi si trova nella prima riga del codice XAML.Al termine, la prima riga dovrebbe essere simile a quella seguente.

    <UserControl x:Class="Page1"
    
  4. Sostituire il contenuto del file Page1.xaml, fatta eccezione per le dichiarazioni usinginizio del file, con il codice seguente.

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

Per creare l'interfaccia utente della seconda pagina della procedura guidata

  1. Nel progetto ProjectTemplateWizard, aprire il menu di scelta rapida per il file Page2.xaml quindi scegliere Apri.

    Il controllo utente verrà visualizzato nella finestra di progettazione.

  2. In visualizzazione XAML, sostituire l'oggetto corrente XAML con il codice XAML seguente.Il codice XAML definisce un'interfaccia utente che comprende un elenco a discesa per la scelta del tipo di base della colonna del sito, una casella combinata per specificare un gruppo incorporato o personalizzato in cui visualizzare la colonna del sito nella raccolta e una casella di testo per specificare il nome della colonna del sito.

    <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. Se si sviluppa un progetto di Visual Basic, rimuovere lo spazio dei nomi ProjectTemplateWizard dal nome della classe Page2 nell'attributo x:Class dell'elemento UserControl.Lo spazio dei nomi si trova nella prima riga del codice XAML.Al termine, la prima riga dovrebbe essere simile a quella seguente.

    <UserControl x:Class="Page2"
    
  4. Sostituire il contenuto del file code-behind per il file Page2.xaml, fatta eccezione per le dichiarazioni usinginizio del file, con il codice seguente.

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

Implementazione della procedura guidata

Definire la funzionalità principale della procedura guidata implementando l'interfaccia IWizard.Questa interfaccia definisce i metodi chiamati da Visual Studio all'avvio e al termine della procedura guidata e in determinati momenti durante l'esecuzione.

Per implementare la procedura guidata

  1. Nel progetto ProjectTemplateWizard aprire il file di codice SiteColumnProjectWizard.

  2. Sostituire tutto il contenuto del file con il codice seguente.

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

Creazione dei comandi SharePoint

Creare due comandi personalizzati che eseguono una chiamata nel modello a oggetti del server SharePoint.Un comando determina se l'URL del sito digitato dall'utente nella procedura guidata è valido.L'altro comando ottiene tutti tipi di campo dal sito di SharePoint specificato in modo che gli utenti possano selezionare quale utilizzare come base per la nuova colonna del sito.

Per definire i comandi di SharePoint

  1. Nel progetto SharePointCommands aprire il file di codice Commands.

  2. Sostituire tutto il contenuto del file con il codice seguente.

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

Verifica

In questa fase della procedura dettagliata, tutto il codice per la procedura guidata si trova nel progetto.Compilare il progetto assicurandosi che tale operazione venga eseguita correttamente.

Per compilare il progetto

  • Sulla barra dei menu, scegliere Compilazione, Compila soluzione.

Rimozione del file key.snk dal modello del progetto

In Procedura dettagliata: creazione di un elemento di progetto Colonna del sito con un modello di progetto, parte 1, il modello del progetto creato contiene un file key.snk utilizzato per firmare ogni istanza del progetto Site Column.Questo file key.snk non è più necessario poiché la procedura guidata genera ora un nuovo file key.snk per ogni progetto.Rimuovere il file key.snk dal modello del progetto e rimuovere i riferimenti a questo file.

Per rimuovere il file key.snk dal modello del progetto

  1. In Esplora soluzioni, nel nodo SiteColumnProjectTemplate, aprire il menu di scelta rapida per il file key.snk quindi scegliere Elimina.

  2. Nella finestra di dialogo di conferma visualizzato, scegliere il pulsante OK.

  3. Nel nodo SiteColumnProjectTemplate, aprire il file SiteColumnProjectTemplate.vstemplate quindi eliminare il seguente elemento da.

    <ProjectItem ReplaceParameters="false" TargetFileName="key.snk">key.snk</ProjectItem>
    
  4. Salvare e chiudere il file.

  5. Nel nodo SiteColumnProjectTemplate, aprire il file ProjectTemplate.csproj o ProjectTemplate.vbproj quindi eliminare il seguente elemento PropertyGroup da.

    <PropertyGroup>
      <SignAssembly>true</SignAssembly>
      <AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
    </PropertyGroup>
    
  6. Rimuovere l'elemento None seguente.

    <None Include="key.snk" />
    
  7. Salvare e chiudere il file.

Associazione della procedura guidata al modello di progetto

Dopo avere implementato la procedura guidata, è necessario associarla al modello di progetto Site Column.A tale scopo, è necessario eseguire tre procedure:

  1. Firmare l'assembly della procedura guidata con un nome sicuro.

  2. Ottenere il token di chiave pubblica per l'assembly della procedura guidata.

  3. Aggiungere un riferimento all'assembly della procedura guidata nel file con estensione vstemplate per il modello di progetto Site Column.

Per firmare l'assembly della procedura guidata con un nome sicuro

  1. In Esplora soluzioni, aprire il menu di scelta rapida del progetto ProjectTemplateWizard quindi scegliere Proprietà.

  2. Nella scheda Firma selezionare la casella di controllo Firma assembly.

  3. Nell'elenco Scegli un file chiave con nome sicuro, scegliere <New...>.

  4. Nella finestra di dialogo Crea chiave con nome sicuro, un nome per il nuovo file di chiave, deselezionare la casella di controllo Proteggi file di chiave con una password quindi scegliere il pulsante OK.

  5. Aprire il menu di scelta rapida del progetto ProjectTemplateWizard quindi scegliere Compilazione per creare il file di ProjectTemplateWizard.dll.

Per ottenere il token di chiave pubblica per l'assembly della procedura guidata

  1. In Menu Start, scegliere Tutti i programmi, scegliere Microsoft Visual Studio 2012, scegliere Visual Studio Toolsquindi scegliere Prompt dei comandi per gli sviluppatori per VS2012.

    Una finestra del prompt dei comandi di Visual Studio viene aperto.

  2. Eseguire il comando seguente, sostituendo PathToWizardAssembly con il percorso completo dell'assembly ProjectTemplateWizard.dll compilato per il progetto ProjectTemplateWizard nel computer di sviluppo:

    sn.exe -T PathToWizardAssembly
    

    Il token di chiave pubblica per l'assembly ProjectTemplateWizard.dll è scritto nella finestra del prompt dei comandi di Visual Studio.

  3. Tenere aperta la finestra del prompt dei comandi di Visual Studio.Il token di chiave pubblica sarà necessario durante la procedura seguente.

Per aggiungere un riferimento all'assembly della procedura guidata nel file con estensione vstemplate

  1. In Esplora soluzioni espandere il nodo del progetto SiteColumnProjectTemplate e aprire il file SiteColumnProjectTemplate.vstemplate.

  2. Alla fine del file, aggiungere l'elemento WizardExtension seguente tra i tag </TemplateContent> e </VSTemplate>.Sostituire il valore token dell'attributo PublicKeyToken con il token di chiave pubblica ottenuto nella procedura precedente.

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

    Per ulteriori informazioni sull'elemento WizardExtension, vedere Elemento WizardExtension (modelli di Visual Studio).

  3. Salvare e chiudere il file.

Aggiunta di parametri sostituibili al file Elements.xml nel modello di progetto

Aggiungere diversi parametri sostituibili al file Elements.xml nel progetto SiteColumnProjectTemplate.Questi parametri vengono inizializzati nel metodo RunStarted della classe SiteColumnProjectWizard definita in precedenza.Quando un utente crea un progetto Site Column, questi parametri nel file Elements.xml nel nuovo progetto vengono sostituiti automaticamente da Visual Studio con i valori specificati nella procedura guidata.

Un parametro sostituibile è un token che inizia e termina con il segno di dollaro ($).Oltre a definire i propri parametri sostituibili, è possibile utilizzare parametri predefiniti, definiti e inizializzati dal sistema del progetto di SharePoint.Per ulteriori informazioni, vedere Parametri sostituibili.

Per aggiungere parametri sostituibili al file Elements.xml

  1. Nel progetto SiteColumnProjectTemplate, sostituire il contenuto del file Elements.xml con il codice XML seguente.

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

    Il nuovo XML modifica i valori degli attributi Name, DisplayName, Type e Group in parametri sostituibili personalizzati.

  2. Salvare e chiudere il file.

Aggiunta della procedura guidata al pacchetto VSIX

Per distribuire la procedura guidata con il pacchetto VSIX che contiene il modello di progetto Site Column, aggiungere riferimenti al progetto di procedura guidata e al progetto dei comandi di SharePoint nel file source.extension.vsixmanifest nel progetto VSIX.

Per aggiungere la procedura guidata al pacchetto VSIX

  1. In Esplora soluzioni, nel progetto SiteColumnProjectItem, aprire il menu di scelta rapida per il file source.extension.vsixmanifest quindi scegliere Apri.

    Visual Studio consente di aprire il file nell'editor del manifesto.

  2. Nella scheda Asset dell'editor, scegliere il pulsante Nuova.

    La finestra di dialogo Aggiungi nuovo asset viene aperto.

  3. Nell'elenco Tipo, scegliere Microsoft.VisualStudio.Assembly.

  4. Nell'elenco Alimentazione, scegliere Progetto nella soluzione corrente.

  5. Nell'elenco Project, scegliere ProjectTemplateWizardquindi scegliere il pulsante OK.

  6. Nella scheda Asset dell'editor, scegliere nuovamente il pulsante Nuova.

    La finestra di dialogo Aggiungi nuovo asset viene aperto.

  7. Nell'elenco Tipo, immettere SharePoint.Commands.v4.

  8. Nell'elenco Alimentazione, scegliere Progetto nella soluzione corrente.

  9. Nell'elenco Project, selezionare il progetto SharePointCommands quindi scegliere il pulsante OK.

  10. Sulla barra dei menu, scegliere Compilazione, Compila soluzionequindi assicurarsi che la soluzione senza errori.

Test della procedura guidata

È ora possibile eseguire il test della procedura guidata.Avviare innanzitutto il debug della soluzione SiteColumnProjectItem nell'istanza sperimentale di Visual Studio.Eseguire quindi il test della procedura guidata per il progetto Site Column nell'istanza sperimentale di Visual Studio.Infine, compilare ed eseguire il progetto per verificare che la colonna del sito funzioni come previsto.

Per avviare il debug della soluzione

  1. Riavviare Visual Studio con credenziali amministrative e aprire la soluzione SiteColumnProjectItem.

  2. Nel progetto ProjectTemplateWizard, aprire il file di codice SiteColumnProjectWizard e aggiungere un punto di interruzione alla prima riga di codice nel metodo RunStarted.

  3. Sulla barra dei menu, scegliere Debug, Eccezioni.

  4. Nella finestra di dialogo Eccezioni, verificare che le caselle di controllo Non gestita dall'utente e Generata per Eccezioni comuni di runtime per le lingue siano deselezionate e quindi scegliere il pulsante OK.

  5. Avviare il debug scegliendo la chiave F5 o, sulla barra dei menu, scegliente Debug, Avvia debug.

    In Visual Studio i file di estensione vengono installati in %UserProfile% \ AppData \ local \ Microsoft \ VisualStudio \ 11.0Exp \ extensions \ Contoso \ site column \ 1,0 e viene avviata un'istanza sperimentale di Visual Studio.L'elemento del progetto verrà testato in questa istanza di Visual Studio.

Per testare la procedura guidata in Visual Studio

  1. Nell'istanza sperimentale di Visual Studio, sulla barra dei menu, scegliere Il file, Nuova, Project.

  2. Espandere il nodo Visual C# o il nodo Visual Basic (a seconda del linguaggio che il modello di progetto supporta), espandere il nodo SharePoint quindi selezionare il nodo 2010.

  3. Nell'elenco di modelli di progetto, scegliere Colonna del sito, denominare il progetto SiteColumnWizardTestquindi scegliere il pulsante OK.

  4. Verificare che il codice nell'altra istanza di Visual Studio venga interrotto in corrispondenza del punto di interruzione impostato precedentemente nel metodo RunStarted.

  5. Continuare a eseguire il debug del progetto scegliendo la chiave F5 o, sulla barra dei menu, scegliente Debug, Continua.

  6. In Personalizzazione guidata SharePoint, immettere l'url del sito che si desidera utilizzare per il debug e quindi scegliere il pulsante Avanti.

  7. Nella seconda pagina di Personalizzazione guidata SharePoint, effettuare le seguenti selezioni:

    • Nell'elenco Tipo, scegliere booleano.

    • Nell'elenco Gruppo, scegliere Colonne Sì/No personalizzate.

    • Nella casella Nome, immettere nella colonna sì/no quindi scegliere il pulsante Fine.

    In Esplora soluzioni, un nuovo progetto contenenente un elemento di progetto denominato Field1e Visual Studio apre il file Elements.xml del progetto nell'editor.

  8. Verificare che il file Elements.xml contenga i valori specificati nella procedura guidata.

Per eseguire il test della colonna del sito in SharePoint.

  1. Nell'istanza sperimentale di Visual Studio, scegliere il tasto F5.

    La colonna del sito viene assemblata e distribuita al sito di SharePoint che la proprietà URL sito del progetto specifica.Il browser viene visualizzata la pagina predefinita di questo sito.

    [!NOTA]

    Se la finestra di dialogo Debug degli script disabilitato viene visualizzato, scegliere il pulsante per continuare il debug del progetto.

  2. Scegliere dal menu Azioni sito, scegliere Impostazioni sito.

  3. Nella pagina impostazioni sito, in Raccolte, scegliere il collegamento Colonne sito.

  4. Nell'elenco delle colonne del sito, verificare che un gruppo Colonne Sì/No personalizzate contenga una colonna denominata Nella colonna sì/noquindi chiudere il browser.

Pulizia del computer di sviluppo

Una volta terminato di eseguire il test dell'elemento di progetto, rimuovere il modello di progetto dall'istanza sperimentale di Visual Studio.

Per pulire il computer di sviluppo

  1. Nell'istanza sperimentale di Visual Studio, sulla barra dei menu, scegliere Strumenti, Estensioni e aggiornamenti.

    La finestra di dialogo Estensioni e aggiornamenti viene aperto.

  2. Nell'elenco di estensioni selezionare, Colonna del sitoquindi scegliere il pulsante Disinstalla.

  3. Nella finestra di dialogo, scegliere il pulsante per confermare che si desidera disinstallare l'estensione e quindi scegliere il pulsante Riavvia ora per completare la disinstallazione.

  4. Chiudere sia l'istanza sperimentale di Visual Studio che l'istanza in cui la soluzione CustomActionProjectItem aperta.

    Per informazioni sulla distribuzione delle estensioni Visual Studio, vedere Distribuzione di un'estensione di Visual Studio.

Vedere anche

Attività

Procedura dettagliata: creazione di un elemento di progetto Colonna del sito con un modello di progetto, parte 1

Procedura: utilizzare procedure guidate con modelli di progetto

Riferimenti

Riferimenti allo schema dei modelli di Visual Studio

IWizard

Concetti

Definizione di tipi di elementi di progetto SharePoint

Creazione di modelli di elemento e di modelli di progetto per gli elementi di progetto SharePoint