SharePoint プロジェクト項目のカスタム種類を定義し、Visual Studio でその種類をプロジェクト テンプレートと関連付けてから、テンプレート用のウィザードを用意することもできます。 ウィザードを使用すると、ユーザーがテンプレートを使用してプロジェクト項目を含む新しいプロジェクトを作成するときに、ユーザーから情報を収集できます。 収集した情報を使用して、プロジェクト項目を初期化できます。
このチュートリアルでは、「チュートリアル: プロジェクト テンプレートに基づくサイト列プロジェクト項目の作成 (パート 1)」で示されている Site Column プロジェクト テンプレートにウィザードを追加します。 ユーザーが Site Column プロジェクトを作成するときに、ウィザードは、サイト内の列に関する情報 (その基本型やグループなど) を収集し、この情報を新しいプロジェクトの Elements.xml ファイルに追加します。
このチュートリアルでは、次のタスクについて説明します。
プロジェクト テンプレートに関連付けるカスタム SharePoint プロジェクト項目の種類に対するウィザードを作成します。
Visual Studio 2010 の SharePoint プロジェクト用の組み込みウィザードと似たカスタム ウィザードの UI を定義します。
ウィザードの実行中にローカル SharePoint サイトへの呼び出しを行うために使用される 2 つの SharePoint コマンドを作成します。 SharePoint コマンドは、SharePoint サーバー オブジェクト モデルの API を呼び出すために Visual Studio 拡張機能で使用できるメソッドです。 詳細については、「SharePoint オブジェクト モデルの呼び出し」を参照してください。
置き換え可能パラメーターを使用して、ウィザードで収集したデータで SharePoint プロジェクト ファイルを初期化します。
新しい各 Site Column プロジェクト インスタンスで新しい .snk ファイルを作成します。 このファイルを使用してプロジェクトの出力に署名し、SharePoint ソリューション アセンブリをグローバル アセンブリ キャッシュに配置できるようにします。
ウィザードをデバッグおよびテストします。
注意
このチュートリアル用の完全なプロジェクト、コード、およびその他のファイルを含むサンプルは、https://go.microsoft.com/fwlink/?LinkId=191369 からダウンロードできます。
必須コンポーネント
このチュートリアルを実行するには、先に「チュートリアル: プロジェクト テンプレートに基づくサイト列プロジェクト項目の作成 (パート 1)」を完了して SiteColumnProjectItem ソリューションを作成しておく必要があります。
また、このチュートリアルを実行するには、開発コンピューターに次のコンポーネントが必要です。
サポート対象エディションの Microsoft Windows、SharePoint、および Visual Studio。 詳細については、「SharePoint ソリューションの開発要件」を参照してください。
Visual Studio 2010 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 ソリューションを開きます。
ソリューション エクスプローラーでソリューション ノードを右クリックし、[追加] をポイントして [新しいプロジェクト] をクリックします。
注意
Visual Basic プロジェクトでは、[全般] ([オプション] ダイアログ ボックス - [プロジェクトおよびソリューション])の [常にソリューションを表示] チェック ボックスがオンになっている場合にのみ、ソリューション ノードが表示されます。
[新しいプロジェクトの追加] ダイアログ ボックスで、[Visual C#] ノードまたは [Visual Basic] ノードを展開し、[Windows] をクリックします。
[新しいプロジェクトの追加] ダイアログ ボックスの上部のコンボ ボックスで、[.NET Framework 4] が選択されていることを確認します。
[WPF ユーザー コントロール ライブラリ] プロジェクト テンプレートを選択します。
[名前] ボックスに「ProjectTemplateWizard」と入力します。
[OK] をクリックします。
Visual Studio によって、ProjectTemplateWizard プロジェクトがソリューションに追加されます。
UserControl1.xaml ファイルをプロジェクトから削除します。
SharePoint コマンド プロジェクトを作成するには
ソリューション エクスプローラーでソリューション ノードを右クリックし、[追加] をポイントして [新しいプロジェクト] をクリックします。
[新しいプロジェクトの追加] ダイアログ ボックスで、[Visual C#] または [Visual Basic] を展開し、[Windows] をクリックします。
[クラス ライブラリ] プロジェクト テンプレートをクリックします。
ダイアログ ボックス上部のコンボ ボックスで、[.NET Framework 3.5] を選択します。
[プロジェクト名] ボックスに「SharePointCommands」と入力します。
[OK] をクリックします。
ソリューションに SharePointCommands プロジェクトが追加され、既定の Class1 コード ファイルが開きます。
Class1 コード ファイルをプロジェクトから削除します。
プロジェクトの構成
ウィザードを作成する前に、いくつかのコード ファイルとアセンブリ参照をプロジェクトに追加する必要があります。
ウィザード プロジェクトを構成するには
ソリューション エクスプローラーで [ProjectTemplateWizard] プロジェクト ノードを右クリックし、[プロパティ] をクリックします。
プロジェクト デザイナーで、ターゲット フレームワークを .NET Framework 4 Client Profile から .NET Framework 4 に変更します。 これは、Visual C# プロジェクトの場合は [アプリケーション] タブで、Visual Basic プロジェクトの場合は [コンパイル] タブで実行できます。 詳細については、「方法: 特定の .NET Framework のバージョンまたはプロファイルを対象として指定する」を参照してください。
注意
既定では、.NET Framework 4 をターゲットとする新しいプロジェクトを作成すると、プロジェクトでクライアント プロファイルがターゲットになります。 このチュートリアルでは、完全な .NET Framework 4 が必要です。
ProjectTemplateWizard プロジェクトで、新しいウィンドウ (WPF) アイテムをプロジェクトに追加します。 アイテムに「WizardWindow」という名前を設定します。
2 つの新しいユーザー コントロール (WPF) アイテムをプロジェクトに追加します。 これらのアイテムに「Page1」および「Page2」という名前を設定します。
次の名前の 4 つのコード ファイルを追加します。
SiteColumnProjectWizard
SiteColumnWizardModel
ProjectSigningManager
CommandIds
[プロジェクト] メニューの [参照の追加] をクリックします。
[.NET] タブで、Ctrl キーを押しながら次のアセンブリをクリックし、[OK] をクリックします。
EnvDTE
Microsoft.VisualStudio.OLE.Interop
Microsoft.VisualStudio.SharePoint
Microsoft.VisualStudio.Shell.10.0
Microsoft.VisualStudio.Shell.Interop.10.0
Microsoft.VisualStudio.TemplateWizardInterface
ソリューション エクスプローラーで、ProjectTemplateWizard プロジェクトの [参照設定] フォルダーの下の [EnvDTE] をクリックします。
注意
[参照設定] フォルダーを表示するには、Visual Basic プロジェクトで、ソリューション エクスプローラーの [すべてのファイルの表示] をクリックする必要があります。
[プロパティ] ウィンドウで、[相互運用型の埋め込み] プロパティを False に変更します。
Visual Basic プロジェクトを開発している場合は、プロジェクト デザイナーを使用して ProjectTemplateWizard 名前空間をプロジェクトにインポートします。 詳細については、「方法 : インポートした名前空間を追加または削除する (Visual Basic)」を参照してください。
SharePointCommands プロジェクトを構成するには
SharePointCommands プロジェクトに、Commands というコード ファイルを追加します。
ソリューション エクスプローラーで、[SharePointCommands] プロジェクト ノードをクリックします。
[プロジェクト] メニューの [既存項目の追加] をクリックします。
[既存項目の追加] ダイアログ ボックスで、ProjectTemplateWizard プロジェクトのコード ファイルが格納されているフォルダーを参照します。
CommandIds コード ファイル選択します。
[追加] ボタンのドロップダウン メニューをクリックし、[リンクとして追加] を選択します。
Visual Studio により、SharePointCommands プロジェクトにリンクとしてコード ファイルが追加されます。 つまり、コード ファイルそのものは ProjectTemplateWizard プロジェクトに存在しますが、そのファイル内のコードは SharePointCommands プロジェクトでもコンパイルされます。
[プロジェクト] メニューの [参照の追加] をクリックします。
[.NET] タブで、Ctrl キーを押しながら次のアセンブリを選択し、[OK] をクリックします。
Microsoft.SharePoint
Microsoft.VisualStudio.SharePoint.Commands
ウィザード モデル、署名マネージャー、および 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 Namespace
namespace 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 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 } }
プロジェクト署名マネージャーを作成するには
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 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 } }
ウィザードの UI の作成
ウィザード ウィンドウの UI と、ウィザード ページの UI を提供する 2 つのユーザー コントロールを定義する XAML を追加し、ウィンドウとユーザー コントロールの動作を定義するコードを追加します。 作成するウィザードは、Visual Studio 2010 の 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.10.0" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" Title="SharePoint Customization Wizard" Height="500" Width="700" ResizeMode="NoResize" Loaded="Window_Loaded" TextOptions.TextFormattingMode="Display"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="75*" /> <RowDefinition Height="364*" /> <RowDefinition Height="1*" /> <RowDefinition Height="60*" /> </Grid.RowDefinitions> <Grid Grid.Row="0" Name="headingGrid" Background="White"> <Label 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 基本クラスから派生します。 カスタムの WPF ダイアログ ボックスを Visual Studio に追加する場合は、ダイアログ ボックスをこのクラスから派生し、スタイルを他の Visual Studio ダイアログ ボックスと一貫させ、発生する可能性のあるモーダル ダイアログの問題を回避することをお勧めします。 詳細については、「How to: Create and Manage Dialog Boxes」を参照してください。
Visual Basic プロジェクトを開発している場合は、Window 要素の x:Class 属性の WizardWindow クラス名から ProjectTemplateWizard 名前空間を削除します。 これは XAML の 1 行目にあります。 変更後の 1 行目は次のようになります。
<Window x:Class="WizardWindow"
WizardWindow.xaml ファイルの分離コード ファイルを開きます。
このファイルの内容全体を次のコードで置き換えます。
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; } } }
1 つ目のウィザード ページの UI を作成するには
Page1.xaml ファイルをダブルクリックし、ユーザー コントロールをデザイナーで開きます。
デザイナーの XAML ビューで、現在の XAML を次の XAML に置き換えます。 この XAML は、ユーザーがデバッグに使用するローカル サイトの URL を入力できるテキスト ボックスと、プロジェクトがサンドボックス ソリューションかどうかを指定するオプション ボタンが含まれる UI を定義します。
<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"
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 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; } } }
2 つ目のウィザード ページの UI を作成するには
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"
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 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; } } }
ウィザードの実装
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 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() { } } }
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 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; } } }
チェックポイント
この段階で、ウィザードに必要なすべてのコードがプロジェクトに揃ったことになります。 エラーが発生することなくプロジェクトをコンパイルできるかどうか、プロジェクトをビルドして確認してください。
プロジェクトをビルドするには
- [ビルド] メニューの [ソリューションのビルド] をクリックします。
プロジェクト テンプレートからの 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] プロジェクト ノードを右クリックし、[プロパティ] をクリックします。
[署名] タブをクリックします。
[アセンブリの署名] チェック ボックスをオンにします。
[厳密な名前のキー ファイルを選択してください] ボックスの一覧の [<新規作成...>] を選択します。
[厳密な名前キーの作成] ダイアログ ボックスで、新しいキー ファイルの名前を入力し、[キー ファイルをパスワードで保護する] チェック ボックスをオフにします。
[OK] をクリックします。
[ビルド] メニューの [ソリューションのビルド] をクリックします。
ウィザード アセンブリの公開キー トークンを取得するには
Visual Studio コマンド プロンプト ウィンドウを開きます。
次のコマンドを実行します。 path to wizard assembly は、開発コンピューター上で ProjectTemplateWizard プロジェクト用にビルドされた ProjectTemplateWizard.dll アセンブリへの完全パスで置き換えます。
sn.exe -T path to wizard assembly
ProjectTemplateWizard.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 プロジェクトの Elements.xml ファイルを開きます。
このファイルの内容を次の 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 によってマニフェスト エディターでファイルが開きます。
エディターの [コンテンツ] セクションで、[コンテンツの追加] をクリックします。
[コンテンツの追加] ダイアログ ボックスで、[コンテンツ タイプの選択] リスト ボックスの [テンプレート ウィザード] をクリックします。
[ソースの選択] の下にある [プロジェクト] をクリックし、その横のリスト ボックスの [ProjectTemplateWizard] を選択します。
[OK] をクリックします。
マニフェスト エディターの [コンテンツの追加] をもう一度クリックします。
[コンテンツの追加] ダイアログ ボックスで、[コンテンツの種類の選択] リスト ボックスの [カスタム拡張機能の種類] をクリックします。
注意
この値は、extension.vsixmanifest ファイル内の CustomExtension 要素に対応します。 Visual Studio の拡張機能に追加するカスタム拡張機能は、この要素によって指定されます。 詳細については、「CustomExtension Element (VSX Schema)」を参照してください。
[種類] ボックスに「SharePoint.Commands.v4」と入力します。
注意
この値は、extension.vsixmanifest ファイル内の CustomExtension 要素の Type 属性に対応します。 カスタム SharePoint コマンドを含んでいるすべてのカスタム拡張機能アセンブリには、Sharepoint.Commands.v4 の値が必須です。
[ソースの選択] の下にある [プロジェクト] をクリックし、その横のリスト ボックスの [SharePointCommands] を選択します。
[OK] をクリックします。
[ビルド] メニューの [ソリューションのビルド] をクリックします。 エラーが発生することなくソリューションがコンパイルされることを確認します。
ウィザードのテスト
これで、ウィザードをテストする準備ができました。 まず、Visual Studio の実験用インスタンスで SiteColumnProjectItem ソリューションのデバッグを開始します。 次に、Visual Studio の実験用インスタンスで、Site Column プロジェクトのウィザードをテストします。 最後に、プロジェクトをビルドして実行し、サイト内の列が正常に機能することを確認します。
ソリューションのデバッグを開始するには
管理者特権で Visual Studio を再起動し、SiteColumnProjectItem ソリューションを開きます。
ProjectTemplateWizard プロジェクトで、SiteColumnProjectWizard コード ファイルを開き、RunStarted メソッド内のコードの 1 行目にブレークポイントを追加します。
[デバッグ] メニューの [例外] をクリックします。
[例外] ダイアログ ボックスで、[Common Language Runtime Exceptions] の [スローされるとき] チェック ボックスと [ユーザーにハンドルされていないとき] チェック ボックスがオフになっていることを確認します。
[OK] をクリックします。
F5 キーを押してデバッグを開始します。
Visual Studio によって、拡張機能が %UserProfile%\AppData\Local\Microsoft\VisualStudio\10.0Exp\Extensions\Contoso\Site Column\1.0 にインストールされ、Visual Studio の実験用インスタンスが開始されます。 このインスタンスの Visual Studio でプロジェクト項目をテストします。
Visual Studio でウィザードをテストするには
Visual Studio の実験用インスタンスで、[ファイル] メニューの [新規] をポイントし、[プロジェクト] をクリックします。
(プロジェクト テンプレートがサポートする言語に応じて) [Visual C#] または [Visual Basic] を展開し、[SharePoint] を展開して、[2010] をクリックします。
プロジェクト テンプレートの一覧で、[Site Column] をクリックします。
[名前] ボックスに「SiteColumnWizardTest」と入力します。
[OK] をクリックします。
Visual Studio のもう一方のインスタンスで、先ほど RunStarted メソッドに設定したブレークポイントで、コードが停止していることを確認します。 F5 キーを押して、プロジェクトのデバッグを続行します。
SharePoint カスタマイズ ウィザードで、デバッグ用のサイトの URL を入力し、[次へ] をクリックします。
SharePoint カスタマイズ ウィザードの 2 つ目のページで、次のように選択します。
[種類] ドロップダウン リストの [ブール型] をクリックします。
[グループ] コンボ ボックスに、「Custom Yes/No Columns」と入力します。
[名前] ボックスに、「My Yes/No Column」と入力します。
[完了] をクリックします。
ソリューション エクスプローラーに、新しいプロジェクトが Field1 という名前のプロジェクト項目と共に表示され、Visual Studio によって Elements.xml ファイルがエディターで開かれます。 Elements.xml にウィザードで指定した値が含まれることを確認します。
SharePoint でサイト内の列をテストするには
Visual Studio の実験用インスタンスで、F5 キーを押します。 サイト内の列がパッケージ化され、プロジェクトの [サイト URL] プロパティで指定された SharePoint サイトに配置されます。 Web ブラウザーには、このサイトの既定のページが表示されます。
注意
[スクリプト デバッグが無効] ダイアログ ボックスが表示された場合は、[はい] をクリックしてプロジェクトをデバッグします。
[サイトの操作] メニューの [サイトの設定] をクリックします。
[ギャラリー] の [サイト内の列] をクリックします。
サイト内の列の一覧で、[My Yes/No Column] という名前の列を含む [Custom Yes/No Columns] グループがあることを確認します。
Web ブラウザーを閉じます。
開発コンピューターのクリーンアップ
プロジェクト項目のテストが終わったら、プロジェクト テンプレートを Visual Studio の実験用インスタンスから削除します。
開発コンピューターをクリーンアップするには
Visual Studio の実験用インスタンスの [ツール] メニューで、[拡張機能マネージャー] をクリックします。
[拡張機能マネージャー] ダイアログ ボックスが表示されます。
拡張機能の一覧で、[Site Column] をクリックし、[アンインストール] をクリックします。
確認のダイアログ ボックスが表示されたら、[はい] をクリックして、拡張機能をアンインストールします。
[今すぐ再起動] をクリックするとアンインストールは完了です。
Visual Studio の両方のインスタンス (実験用インスタンスと SiteColumnProjectItem ソリューションを開いたインスタンス) を閉じます。
参照
処理手順
方法 : プロジェクト テンプレートを組み合わせたウィザードを使用する