SharePoint プロジェクト項目のカスタム種類を定義し、Visual Studio でその種類をプロジェクト テンプレートと関連付けてから、テンプレート用のウィザードを用意することもできます。ウィザードを使用すると、ユーザーがテンプレートを使用してプロジェクト項目を含む新しいプロジェクトを作成するときに、ユーザーから情報を収集できます。収集した情報を使用して、プロジェクト項目を初期化できます。
このチュートリアルでは、「チュートリアル: プロジェクト テンプレートに基づくサイト列プロジェクト項目の作成 (パート 1)」で示されている Site Column プロジェクト テンプレートにウィザードを追加します。ユーザーが Site Column プロジェクトを作成するときに、ウィザードは、サイト内の列に関する情報 (その基本型やグループなど) を収集し、この情報を新しいプロジェクトの Elements.xml ファイルに追加します。
このチュートリアルでは、次のタスクを実行します。
プロジェクト テンプレートに関連付けるカスタム SharePoint プロジェクト項目の種類に対するウィザードを作成します。
カスタム ウィザードのUIを定義するには、Visual StudioでのSharePointプロジェクト用の組み込みウィザードと似た。
ウィザードの実行中にローカル SharePoint サイトへの呼び出しを行うために使用される 2 つの SharePoint コマンドを作成します。SharePoint コマンドは、SharePoint サーバー オブジェクト モデルの API を呼び出すために Visual Studio 拡張機能で使用できるメソッドです。詳細については、「SharePoint オブジェクト モデルの呼び出し」を参照してください。
置き換え可能パラメーターを使用して、ウィザードで収集したデータで SharePoint プロジェクト ファイルを初期化します。
新しい各 Site Column プロジェクト インスタンスで新しい .snk ファイルを作成します。このファイルを使用してプロジェクトの出力に署名し、SharePoint ソリューション アセンブリをグローバル アセンブリ キャッシュに配置できるようにします。
ウィザードをデバッグおよびテストします。
[!メモ]
このチュートリアル用の完全なプロジェクト、コード、およびその他のファイルを含むサンプルは、https://go.microsoft.com/fwlink/?LinkId=191369 からダウンロードできます。
必須コンポーネント
このチュートリアルを実行するには、先に「チュートリアル: プロジェクト テンプレートに基づくサイト列プロジェクト項目の作成 (パート 1)」を完了して SiteColumnProjectItem ソリューションを作成しておく必要があります。
また、このチュートリアルを実行するには、開発コンピューターに次のコンポーネントが必要です。
Windows SharePoint、およびサポートされるVisual Studioのエディション。詳細については、「SharePoint ソリューションの開発要件」を参照してください。
Visual Studio SDK。このチュートリアルでは、SDK の VSIX プロジェクト テンプレートを使用して、プロジェクト項目を配置するための VSIX パッケージを作成します。詳細については、「Visual Studio の SharePoint ツールの拡張」を参照してください。
次の概念に関する知識があると役に立ちますが、チュートリアルを実行するうえで必須というわけではありません。
Visual Studio のプロジェクトおよび項目テンプレート用のウィザード。詳細については、「方法 : プロジェクト テンプレートを組み合わせたウィザードを使用する」および IWizard インターフェイスを参照してください。
SharePoint のサイト内の列。詳細については、「列」を参照してください。
ウィザードのコンポーネントについて
このチュートリアルで説明されているウィザードには、いくつかのコンポーネントが含まれています。次の表は、これらのコンポーネントについての説明です。
コンポーネント |
説明 |
|---|---|
ウィザード実装 |
これは SiteColumnProjectWizard という名前のクラスであり、IWizard インターフェイスを実装します。このインターフェイスは、ウィザードの起動および終了時と、ウィザードの実行中の特定のタイミングで Visual Studio によって呼び出されるメソッドを定義します。 |
ウィザード UI |
これは、WizardWindow という名前の WPF ベースのウィンドウです。このウィンドウには、Page1 および Page2 という名前の 2 つのユーザー コントロールが含まれます。これらのユーザー コントロールは、ウィザードの 2 つのページを表します。 このチュートリアルでは、ウィザード実装の RunStarted メソッドによって、ウィザード UI が表示されます。 |
ウィザード データ モデル |
これは、SiteColumnWizardModel という名前の中間クラスであり、ウィザード UI とウィザード実装の間のレイヤーを提供します。このサンプルでは、このクラスを使用して、ウィザード実装とウィザード UI を互いに抽象化できるようにします。このクラスは、すべてのウィザードで必須コンポーネントとなるわけではありません。 このチュートリアルでは、ウィザード UI が表示されるときに、ウィザード実装によって、ウィザード ウィンドウに SiteColumnWizardModel オブジェクトが渡されます。ウィザード UI は、このオブジェクトのメソッドを使用して UI にコントロールの値を保存し、入力されたサイト URL が有効であることの確認などのタスクを実行します。ユーザーがウィザードを終了すると、ウィザード実装は SiteColumnWizardModel オブジェクトを使用して、UI の最終的な状態を判断します。 |
プロジェクト署名マネージャー |
これは、ProjectSigningManager という名前のヘルパー クラスであり、新しい各プロジェクト インスタンスで新しい key.snk ファイルを作成するためにウィザード実装によって使用されます。 |
SharePoint コマンド |
これらは、ウィザードの実行中にローカル SharePoint サイトへの呼び出しを行うためにウィザード データ モデルによって使用されるメソッドです。SharePoint コマンドは .NET Framework 3.5 をターゲットとする必要があるため、これらのコマンドは他のウィザード コードとは異なるアセンブリに実装されます。 |
プロジェクトの作成
このチュートリアルを行うには、「チュートリアル: プロジェクト テンプレートに基づくサイト列プロジェクト項目の作成 (パート 1)」で作成した SiteColumnProjectItem ソリューションにいくつかのプロジェクトを追加する必要があります。
WPF プロジェクト。このプロジェクトで、IWizard インターフェイスを実装し、ウィザードの UI を定義します。
SharePoint コマンドを定義するクラス ライブラリ プロジェクト。このプロジェクトは .NET Framework 3.5 を対象にする必要があります。
この 2 つのプロジェクトを作成することから始めます。
WPF プロジェクトを作成するには
Visual Studioで、SiteColumnProjectItemソリューションを開きます。
[ソリューション エクスプローラー]では、[SiteColumnProjectItem] のソリューション ノードのショートカット メニューを開き、**[追加]**を選択し、を **[新しいプロジェクト]**を選択します。
[!メモ]
Visual Basic プロジェクトでは、General, Projects and Solutions, Options Dialog Boxの [常にソリューションを表示] チェック ボックスがオンになっている場合にのみ、ソリューション ノードが表示されます。
[新しいプロジェクトの追加] のダイアログ ボックスの上部に、[.NET Framework 4.5] が.NET Frameworkのバージョンの一覧で、が選択されていることを確認します。
[Visual C#] の [Visual Basic] のノードまたはノードを展開し、[ウィンドウ] のノードを選択します。
プロジェクト テンプレートの一覧で、[WPF ユーザー コントロール ライブラリ]を選択し、プロジェクト [ProjectTemplateWizard]を付けておくと、[OK] のボタンをクリックします。
Visual Studio は [ProjectTemplateWizard] のソリューションにプロジェクトを追加し、既定でUserControl1.xamlファイルを開きます。
UserControl1.xaml ファイルをプロジェクトから削除します。
SharePoint コマンド プロジェクトを作成するには
**[ソリューション エクスプローラー]で、SiteColumnProjectItemソリューション ノードのショートカット メニューを開き、[追加]**を選択し、を **[新しいプロジェクト]**を選択します。
[新しいプロジェクトの追加] のダイアログ ボックスの上部に、.NET Frameworkのバージョンの [.NET Framework 3.5] リストのを選択します。
[Visual C#] の [Visual Basic] のノードまたはノードを展開し、[ウィンドウ] のノードを選択します。
[クラス ライブラリ] のプロジェクト テンプレートを選択し、プロジェクト [SharePointCommands]を付けておくと、[OK] のボタンをクリックします。
Visual Studio は [SharePointCommands] のソリューションにプロジェクトが追加され、既定のClass1コード ファイルが開きます。
Class1 コード ファイルをプロジェクトから削除します。
プロジェクトの構成
ウィザードを作成する前に、プロジェクトに対してコード ファイルおよびアセンブリ参照を追加する必要があります。
ウィザード プロジェクトを構成するには
[ソリューション エクスプローラー]では、[ProjectTemplateWizard] のプロジェクト ノードのショートカット メニューを開き、**[プロパティ]**を選択します。
**[プロジェクト デザイナー]**では、Visual C#プロジェクトの [アプリケーション] のタブ、Visual Basicプロジェクトの [コンパイル] のタブをクリックします。
.NET Framework 4.5 Client Profileのではなく、をに設定するターゲット フレームワークを.NET Framework 4.5確認します。
詳細については、「方法: .NET Framework のバージョンをターゲットにする」を参照してください。
[ProjectTemplateWizard] のプロジェクトのショートカット メニューを開き、**[追加]**を選択し、を **[新しい項目]**を選択します。
[ウィンドウ (WPF)] の項目を選択し、項目 WizardWindowを付けておくと、[追加] のボタンをクリックします。
[ユーザー コントロール (WPF)] の2項目をプロジェクトに追加し、Page1 と Page2という名前を付けます。
4種類のコード ファイルをプロジェクトに追加し、次の名前を指定します:
SiteColumnProjectWizard
SiteColumnWizardModel
ProjectSigningManager
CommandIds
[ProjectTemplateWizard] のプロジェクト ノードのショートカット メニューを開き、**[参照の追加]**を選択します。
[アセンブリ] のノードを展開し、[拡張機能] のノードを選択し、次のアセンブリの横にあるチェック ボックスをオンにします:
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
プロジェクトにアセンブリを追加するに [OK] のボタンをクリックします。
[ProjectTemplateWizard] のプロジェクトの [参照] フォルダーの下の **[ソリューション エクスプローラー]では、[EnvDTE]**を選択します。
[!メモ]
Visual Basic プロジェクトでは、[参照設定] フォルダーが表示されるのは、General, Projects and Solutions, Options Dialog Box で [常にソリューションを表示] チェック ボックスがオンになっている場合のみです。
[プロパティ] のペインで、**[false]**に [相互運用型の埋め込み] のプロパティの値を変更します。
Visual Basicプロジェクトを開発している場合は、**[プロジェクト デザイナー]**を使用してプロジェクトに ProjectTemplateWizard の名前空間をインポートします。
詳細については、「方法 : インポートした名前空間を追加または削除する (Visual Basic)」を参照してください。
SharePointCommands プロジェクトを構成するには
[ソリューション エクスプローラー]では、[SharePointCommands] のプロジェクト ノードを選択します。
メニュー バーで、[プロジェクト]、**[既存項目の追加]**を選択します。
[既存項目の追加] のダイアログ ボックスで、ProjectTemplateWizardプロジェクトのコード ファイルが格納されているフォルダーを参照し、次に [CommandIds] コード ファイルにフォルダーを選択します。
矢印を [追加] のボタンの横にあるを選択し、表示されるメニューの [リンクとして追加] のオプションを選択します。
Visual Studio はリンクとして [SharePointCommands] のプロジェクトには、コード ファイルを追加します。コード ファイルは [ProjectTemplateWizard] プロジェクトにありますが、ファイル内のコードが、[SharePointCommands] のプロジェクトでコンパイルされます。
[SharePointCommands] のプロジェクトでは、Commandsという名前のコード ファイルを追加します。
次に、SharePointCommandsおよび、メニュー バーで、をクリックします [プロジェクト]、**[参照の追加]**を選択します。
[アセンブリ] のノードを展開し、[拡張機能] のノードを選択し、次のアセンブリの横にあるチェック ボックスをオンにします:
Microsoft.SharePoint
Microsoft.VisualStudio.SharePoint.Commands
プロジェクトにアセンブリを追加するに [OK] のボタンをクリックします。
ウィザード モデル、署名マネージャー、および SharePoint コマンド ID の作成
ProjectTemplateWizard プロジェクトにコードを追加して、サンプルの次のコンポーネントを実装します。
SharePoint コマンド ID。これらの文字列は、SharePointコマンドを識別します。ウィザードの使用後の手順で、SharePointCommandsにコードをコマンドの実行をプロジェクトに追加します。
ウィザード データ モデル。
プロジェクト署名マネージャー。
これらのコンポーネントの詳細については、「ウィザードのコンポーネントについて」を参照してください。
SharePoint コマンド ID を定義するには
ProjectTemplateWizardプロジェクトで、CommandIdsコード ファイルを開き、次のコードでこのファイルの内容を置き換えます。
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 Namespacenamespace Contoso.SharePoint.Commands { public static class CommandIds { public const string GetFieldTypes = "Contoso.Commands.GetFieldTypes"; public const string ValidateSite = "Contoso.Commands.ValidateSite"; } }
ウィザード モデルを作成するには
SiteColumnWizardModelコード ファイルを開き、次のコードでこのファイルの内容を置き換えます。
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 Classusing 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 } }
プロジェクト署名マネージャーを作成するには
ProjectSigningManagerコード ファイルを開き、次のコードでこのファイルの内容を置き換えます。
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 Classusing 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 } }
ウィザードの UI の作成
ウィザード ウィンドウの UI と、ウィザード ページの UI を提供する 2 つのユーザー コントロールを定義する XAML を追加し、ウィンドウとユーザー コントロールの動作を定義するコードを追加します。作成するウィザードは、Visual Studio の SharePoint プロジェクト用の組み込みウィザードに似ています。
[!メモ]
以降の手順では、プロジェクトに XAML またはコードを追加した後で、いくつかのコンパイル エラーが発生します。これらのエラーは、この後の手順でコードを追加すると解消されます。
ウィザード ウィンドウの UI を作成するには
ProjectTemplateWizardプロジェクトで、WizardWindow.xamlファイルのショートカット メニューを開き、ウィンドウをデザイナーで開くに [開く] を選択します。
デザイナーの XAML ビューで、現在の XAML を次の XAML に置き換えます。この XAML は、見出しを含む UI、ウィザード ページが含まれる Grid、およびウィンドウの下部に示されるナビゲーション ボタンを定義します。
<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="< _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>[!メモ]
このXAMLで作成するウィンドウは DialogWindow の基本クラスから派生します。Visual StudioにカスタムのWPFダイアログ ボックスを追加する場合は、他のVisual Studioのダイアログ ボックスで一貫したスタイルを使用すると、別の方法で発生する可能性のあるモーダル ダイアログの問題を回避するには、このクラスからダイアログ ボックスを取得することをお勧めします。詳細については、「方法 : ダイアログ ボックスを作成して管理する。」を参照してください。
Visual Basicプロジェクトを開発している場合は、Window の要素の x:Class の属性の WizardWindow の ProjectTemplateWizard のクラス名から名前空間を削除します。この要素は、の最初の行にあります。されると、最初の行は次の例のようになります。
<Window x:Class="WizardWindow"WizardWindow.xaml ファイルの分離コード ファイルを開きます。
次のコードをファイルの先頭に using の宣言を除き、ファイルの内容を、置換します。
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 Classusing 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; } } }
1 つ目のウィザード ページの UI を作成するには
ProjectTemplateWizardプロジェクトで、Page1.xamlファイルのショートカット メニューを開き、ユーザー コントロールをデザイナーで開くに [開く] を選択します。
デザイナーの XAML ビューで、現在の XAML を次の XAML に置き換えます。userはデバッグに使用するローカル サイトのURLを入力できるテキスト ボックスが含まれているXAMLはUIを定義します。UIには、userは、プロジェクトがサンドボックス ソリューションかどうかを指定するオプション ボタンが含まれています。
<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>Visual Basic プロジェクトを開発している場合は、UserControl 要素の x:Class 属性の Page1 クラス名から ProjectTemplateWizard 名前空間を削除します。これは XAML の 1 行目にあります。変更後の 1 行目は次のようになります。
<UserControl x:Class="Page1"次のコードをファイルの先頭に using の宣言を除くPage1.xamlファイルの内容を、置換します。
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 Classusing 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; } } }
2 つ目のウィザード ページの UI を作成するには
ProjectTemplateWizardプロジェクトで、Page2.xamlファイルのショートカット メニューを開き、**[開く]**を選択します。
ユーザー コントロールがデザイナーで開きます。
XAMLビューで、次のXAMLに現在のXAMLに置き換えます。この XAML は、サイト内の列の基本型を選択するためのドロップダウン リスト、ギャラリーでサイト内の列を表示する組み込みまたはカスタムのグループを指定するためのコンボ ボックス、およびサイト内の列の名前を指定するためのボックスが含まれる UI を定義します。
<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>Visual Basic プロジェクトを開発している場合は、UserControl 要素の x:Class 属性の Page2 クラス名から ProjectTemplateWizard 名前空間を削除します。これは XAML の 1 行目にあります。変更後の 1 行目は次のようになります。
<UserControl x:Class="Page2"次のコードをファイルの先頭に using の宣言を除くPage2.xamlファイルの分離コード ファイルの内容を、置換します。
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 Classusing 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; } } }
ウィザードの実装
IWizard インターフェイスを実装することで、ウィザードの主要機能を定義します。このインターフェイスは、ウィザードの起動および終了時と、ウィザードの実行中の特定のタイミングで Visual Studio によって呼び出されるメソッドを定義します。
ウィザードを実装するには
ProjectTemplateWizard プロジェクトで、SiteColumnProjectWizard コード ファイルを開きます。
このファイルの内容全体を次のコードで置き換えます。
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 Classusing 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() { } } }
SharePoint コマンドの作成
SharePoint サーバー オブジェクト モデルを呼び出す 2 つのカスタム コマンドを作成します。一方のコマンドは、ウィザードでユーザーが入力するサイトの URL が有効かどうかを判断します。もう一方のコマンドは、指定した SharePoint サイトからすべてのフィールドの型を取得して、ユーザーが新しいサイト内の列の基本として使用するフィールドの型を選択できるようにします。
SharePoint コマンドを定義するには
SharePointCommands プロジェクトの Commands コード ファイルを開きます。
このファイルの内容全体を次のコードで置き換えます。
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 Namespaceusing 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; } } }
チェックポイント
この段階で、ウィザードに必要なすべてのコードがプロジェクトに揃ったことになります。エラーが発生することなくプロジェクトをコンパイルできるかどうか、プロジェクトをビルドして確認してください。
プロジェクトをビルドするには
- メニュー バーで、[ビルド]、**[ソリューションのビルド]**を選択します。
プロジェクト テンプレートからの key.snk ファイルの削除
「チュートリアル: プロジェクト テンプレートに基づくサイト列プロジェクト項目の作成 (パート 1)」では、作成したプロジェクト テンプレートに、各 Site Column プロジェクト インスタンスに署名するために使用される key.snk ファイルが含まれています。ウィザードでプロジェクトごとに新しい key.snk ファイルが生成されるようになったため、この key.snk ファイルはもう必要ありません。プロジェクト テンプレートから key.snk ファイルを削除し、このファイルへの参照を削除します。
プロジェクト テンプレートから key.snk ファイルを削除するには
[ソリューション エクスプローラー]では、[SiteColumnProjectTemplate] のノードの下で、を開き、[key.snk] ファイルのショートカット メニューで、を **[削除]**を選択します。
表示される確認のダイアログ ボックスで、[OK] のボタンをクリックします。
[SiteColumnProjectTemplate] のノードの下で、SiteColumnProjectTemplate.vstemplateファイルを開き、そこから次の要素を削除します。
<ProjectItem ReplaceParameters="false" TargetFileName="key.snk">key.snk</ProjectItem>ファイルを保存して閉じます。
[SiteColumnProjectTemplate] ノードの下のProjectTemplate.csprojファイルまたはProjectTemplate.vbprojファイルを開き、そこから PropertyGroup の次の要素を削除します。
<PropertyGroup> <SignAssembly>true</SignAssembly> <AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile> </PropertyGroup>次の None 要素を削除します。
<None Include="key.snk" />ファイルを保存して閉じます。
ウィザードとプロジェクト テンプレートの関連付け
ウィザードの実装が済んだので、ウィザードと Site Column プロジェクト テンプレートを関連付ける必要があります。これを行うために必要となる手順は次の 3 つです。
ウィザード アセンブリに厳密な名前で署名します。
ウィザード アセンブリの公開キー トークンを取得します。
Site Column プロジェクト テンプレートの .vstemplate ファイルに、ウィザード アセンブリへの参照を追加します。
ウィザード アセンブリに厳密な名前で署名するには
[ソリューション エクスプローラー]では、[ProjectTemplateWizard] のプロジェクトのショートカット メニューを開き、**[プロパティ]**を選択します。
[署名] タブの [アセンブリの署名] チェック ボックスをオンにします。
[厳密な名前のキー ファイルを選択してください] の一覧で、を選択 **<New...>**します。
[厳密な名前キーの作成] のダイアログ ボックスで、新しいキー ファイルの名前を入力し、[キーファイルをパスワードで保護する] のチェック ボックスをオフにし、を [OK] のボタンをクリックします。
[ProjectTemplateWizard] のプロジェクトのショートカット メニューを開き、ProjectTemplateWizard.dllファイルを作成するに [ビルド] を選択します。
ウィザード アセンブリの公開キー トークンを取得するには
**[スタート メニュー]で、[All Programs]を選択し、[Microsoft Visual Studio 2012]を選択し、[Visual Studio ツール]**を選択し、を **[VS2012 の開発者コマンド プロンプト]**を選択します。
Visual Studioのコマンド プロンプト ウィンドウで開きます。
開発用コンピューターでProjectTemplateWizardプロジェクトのビルドされたProjectTemplateWizard.dllアセンブリに完全パスで PathToWizardAssembly を置き換える次のコマンドを実行する:
sn.exe -T PathToWizardAssemblyProjectTemplateWizard.dll アセンブリに対する公開キー トークンが Visual Studio コマンド プロンプト ウィンドウに記述されます。
Visual Studio コマンド プロンプト ウィンドウは開いたままにします。次の手順の間に、公開キー トークンが必要になります。
.vstemplate ファイルにウィザード アセンブリへの参照を追加するには
ソリューション エクスプローラーで、[SiteColumnProjectTemplate] プロジェクト ノードを展開し、SiteColumnProjectTemplate.vstemplate ファイルを開きます。
ファイルの末尾の近くで、次の WizardExtension 要素を </TemplateContent> タグと </VSTemplate> タグの間に追加します。PublicKeyToken 属性の your token の値は、前の手順で取得した公開キー トークンで置き換えます。
<WizardExtension> <Assembly>ProjectTemplateWizard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=your token</Assembly> <FullClassName>ProjectTemplateWizard.SiteColumnProjectWizard</FullClassName> </WizardExtension>WizardExtension 要素の詳細については、「WizardExtension 要素 (Visual Studio テンプレート)」を参照してください。
ファイルを保存して閉じます。
プロジェクト テンプレートの Elements.xml ファイルへの置き換え可能パラメーターの追加
複数の置き換え可能パラメーターを、SiteColumnProjectTemplate プロジェクトの Elements.xml ファイルに追加します。これらのパラメーターは、前に定義した SiteColumnProjectWizard クラスの RunStarted メソッドで初期化されます。ユーザーが Site Column プロジェクトを作成すると、Visual Studio によって自動的に、新しいプロジェクト項目の Elements.xml ファイル内のこれらのパラメーターが、ウィザードでユーザーが指定した値に置き換えられます。
置き換え可能パラメーターはトークンであり、先頭と末尾にはドル記号 ($) が付いています。独自の置き換え可能パラメーターを定義するだけでなく、SharePoint プロジェクト システムによって定義されて初期化される組み込みパラメーターを使用することもできます。詳細については、「置き換え可能パラメーター」を参照してください。
置き換え可能パラメーターを Elements.xml ファイルに追加するには
で、SiteColumnProjectTemplateプロジェクトの次のXMLにElements.xmlファイルの内容を置き換えます。
<?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>新しい XML では、Name、DisplayName、Type、Group の各属性の値がカスタムの置き換え可能パラメーターに変更されます。
ファイルを保存して閉じます。
VSIX パッケージへのウィザードの追加
Site Column プロジェクト テンプレートが含まれる VSIX パッケージと共にウィザードを配置するには、ウィザード プロジェクトと SharePoint コマンド プロジェクトへの参照を VSIX プロジェクトの source.extension.vsixmanifest ファイルに追加します。
VSIX パッケージにウィザードを追加するには
[ソリューション エクスプローラー]では、[SiteColumnProjectItem] のプロジェクトで、を開き、[source.extension.vsixmanifest] ファイルのショートカット メニューで、を **[開く]**を選択します。
Visual Studio によってマニフェスト エディターでファイルが開きます。
エディターの [資産] のタブで、[新規作成] のボタンをクリックします。
[新しい資産の追加] のダイアログ ボックスが表示されます。
[種類] の一覧で、**[Microsoft.VisualStudio.Assembly]**を選択します。
[ソース] の一覧で、**[現在のソリューション内のプロジェクト]**を選択します。
[プロジェクト] の一覧で、[ProjectTemplateWizard]を選択し、[OK] のボタンをクリックします。
エディターの [資産] のタブで、[新規作成] のボタンをもう一度クリックします。
[新しい資産の追加] のダイアログ ボックスが表示されます。
[種類] の一覧で、**[SharePoint.Commands.v4]**を入力します。
[ソース] の一覧で、**[現在のソリューション内のプロジェクト]**を選択します。
[プロジェクト] の一覧で、[SharePointCommands] プロジェクトを選択し、[OK] のボタンをクリックします。
メニュー バーで、[ビルド]、**[ソリューションのビルド]**を選択し、ソリューションがエラーなしでビルドされることを確認します。
ウィザードのテスト
これで、ウィザードをテストする準備ができました。まず、Visual Studio の実験用インスタンスで SiteColumnProjectItem ソリューションのデバッグを開始します。次に、Visual Studio の実験用インスタンスで、Site Column プロジェクトのウィザードをテストします。最後に、プロジェクトをビルドして実行し、サイト内の列が正常に機能することを確認します。
ソリューションのデバッグを開始するには
管理資格情報を使用してVisual Studioを再起動し、SiteColumnProjectItemソリューションを開きます。
ProjectTemplateWizardプロジェクトで、SiteColumnProjectWizardコード ファイルを開き、RunStarted のメソッドのコードの先頭行にブレークポイントを追加します。
メニュー バーで、[デバッグ]、**[例外]**を選択します。
[例外] のダイアログ ボックスで、[Common Language Runtime Exceptions] の [スローされるとき] と [ユーザーにハンドルされていないとき] のチェック ボックスがオフになっていることを確認し、次に [OK] のボタンを選択します。
[F5] キーのまたはを選択する [デバッグ]、メニュー バーのをクリックしてデバッグを開始した [デバッグの開始]。
Visual Studioは、%UserProfile%\AppData\Local\Microsoft\VisualStudio\11.0Exp\Extensions\Contoso\Site Column\1.0に拡張機能をインストール、Visual Studioの実験用インスタンスを起動します。Visual Studioでプロジェクト項目をテストします。この場合
Visual Studio でウィザードをテストするには
Visual Studioの実験用インスタンスで、メニュー バーで、[ファイル]、[新規作成]、**[プロジェクト]**を選択します。
[Visual C#] のノードまたはノード ([Visual Basic] のプロジェクト テンプレートがサポートする言語に応じて) [SharePoint] 展開し、ノードを展開し、を [2010] のノードを選択します。
プロジェクト テンプレートの一覧で、[サイト列]を選択し、プロジェクト SiteColumnWizardTestを付けておくと、[OK] のボタンをクリックします。
Visual Studio のもう一方のインスタンスで、先ほど RunStarted メソッドに設定したブレークポイントで、コードが停止していることを確認します。
または、**[デバッグ]**を選択するメニュー バーで [続行][F5] のキーをクリックして、プロジェクトのデバッグを続行します。
**[SharePoint カスタマイズ ウィザード]**では、デバッグ用に使用する入力し、次に [次へ] のボタンを選択します。サイトのURL。
SharePoint カスタマイズ ウィザードの 2 つ目のページで、次のように選択します。
[種類] の一覧で、**[ブール型]**を選択します。
[グループ] の一覧で、**[Custom Yes/No Columns]**を選択します。
[名前] ボックスに、My Yes/No列を入力し、を [完了] のボタンをクリックします。
**[ソリューション エクスプローラー]で、新しいプロジェクトが表示され、[フィールド 1]**という、Visual Studioは、エディターのプロジェクトのElements.xmlファイルを開きますプロジェクト項目が含まれます。
Elements.xml にウィザードで指定した値が含まれることを確認します。
SharePoint でサイト内の列をテストするには
Visual Studioの実験用インスタンスで、F5キーのキーを選択します。
サイト内の列の [サイト URL] は、プロジェクトのプロパティで指定されたSharePointサイトにパッケージ化および配置されます。Webブラウザーには、このサイトの既定のページが表示されます。
[!メモ]
[スクリプト デバッグが無効] ダイアログ ボックスで、プロジェクトのデバッグを続行に [○] のボタンをクリックします。
[サイト アクション] で、メニューの **[サイトの設定]**を選択します。
[サイトの設定] ページで、[ギャラリー]の下に、[サイト列] のリンクを選択します。
サイト内の列の一覧で、[Custom Yes/No Columns] のグループが **[My Yes/No Column]**という含まれ、Webブラウザーを閉じる列をことを確認します。
開発コンピューターのクリーンアップ
プロジェクト項目のテストが終わったら、プロジェクト テンプレートを Visual Studio の実験用インスタンスから削除します。
開発コンピューターをクリーンアップするには
Visual Studioの実験用インスタンスで、メニュー バーで、[ツール]、**[拡張機能と更新プログラム]**を選択します。
[拡張機能と更新プログラム] のダイアログ ボックスが表示されます。
拡張機能の一覧で、[サイト列]を選択し、[アンインストール] のボタンをクリックします。
表示されたダイアログ ボックスで、拡張機能をアンインストールする選択し、アンインストールを実行するに [今すぐ再起動] のボタンを選択します。ことを確認するために [○] のボタンをクリックします。
CustomActionProjectItemソリューションを開いたVisual Studioの実験用インスタンスとインスタンスの両方を閉じます。
Visual Studio の拡張機能の配置方法の詳細については、Visual Studio 拡張機能の配置を参照してください。
参照
処理手順
チュートリアル: プロジェクト テンプレートに基づくサイト列プロジェクト項目の作成 (パート 1)
方法 : プロジェクト テンプレートを組み合わせたウィザードを使用する