次の方法で共有


チュートリアル: JS グリッドを使用して Project Server Web パーツを作成する

適用対象: Office 2010 | Project 2010 | Project Server 2010 | SharePoint Server 2010

Project Web App の多くのページには JS グリッド コントロールが含まれています。JS グリッド コントロールは、Microsoft Project Server 2010 の Web パーツ内で表形式のデータを表示および操作するのにも役立ちます。この記事では、ListProjects PSI 拡張機能を呼び出し、JS グリッド コントロールを使用して、指定のユーザー設定フィールド値が格納されているすべてのプロジェクトを表示する Web パーツを開発する方法について説明します。編集可能な Project Web App ページ、プロジェクト詳細ページ (PDP)、およびプロジェクト サイト ページに、同じ Web パーツを追加できます (この記事と、Project 2010 SDK ダウンロード内の ListProjects サンプルに含まれている JS グリッド コントロール コードは、Sivaraman Krishnan および Andrew Cuneo (Microsoft Corporation) によるサンプルに基づいています)。

この記事は次のセクションで構成されます。

  • ListProjects Web パーツの開発

    • Web パーツの作成

    • ユーザー コントロールの変更

    • 構成用の Web パーツ プロパティの追加

    • 最初の使用時における構成の要求

    • JS グリッド コントロールの初期化

  • ListProjects Web パーツのテスト

    • Project Web App ページへの ListProjects の追加

    • ListProjects Web パーツの展開

    • プロジェクト詳細ページへの ListProjects の追加

    • プロジェクト サイト ページへの ListProjects の追加

ListProjects Web パーツの完全なソース コードは Project 2010 SDK ダウンロードにあります。この記事内のコードは、ダウンロードの Samples\WebParts\ListProjects サブディレクトリにあります。列の並べ替えが有効なバージョンのコードは、Samples\WebParts\ListProjects_Sorting サブディレクトリにあります。ダウンロードへのリンクについては、「Project 2010 SDK のドキュメント」を参照してください。ListProjects PSI 拡張機能の詳細については、「[方法] RDB のユーザー設定フィールドを読み取る PSI 拡張を作成する方法」を参照してください。JS グリッド コントロールの使用および Project Web App のカスタマイズのビデオ デモについては、「Developing Custom Solutions in PWA (英語)」を参照してください。Web パーツの詳細については、「User Interface Customization Resource Center | SharePoint 2010 (英語)」を参照してください。

前提条件

Microsoft Project Server 2010 用の Web パーツを開発するには Microsoft Visual Studio 2010 が必要です。Visual Studio による SharePoint 機能の自動インストールとデバッグを有効にするには、Project Server を実行しているコンピューター上で開発を行う必要があります。Visual Studio プロジェクトの対象は Microsoft .NET Framework 3.5 にします。

注意

Project Web App のカスタマイズの開発およびテストは必ず Project Server 2010 のテスト インストール上で行ってください。

ソリューションが完成して全体をテストする場合は、「ListProjects Web パーツの展開」に記載されている Windows PowerShell コマンドを使用して, .wsp ソリューション ファイルを運用サーバーに展開します。

ListProjects Web パーツの開発

ListProjects Web パーツのサンプルには、ListProjectsPart という名前の視覚的 Web パーツ アイテムが含まれています。この Web パーツは、Web パーツを初めて使用するときに設定する必要がある 5 つのプロパティを持ちます。Web パーツ コントロールの名前は ListProjectsPartUserControl です。

Web パーツの作成

次の手順は、「Project Server Web パーツの開発」の一般的な情報に基づいています。

手順 1. ListProjects Web パーツを作成するには

  1. ローカル Project Server コンピューター上で管理者として Visual Studio 2010 を実行します。ListProjects という名前の空の SharePoint 2010 プロジェクトを作成します。ターゲットのフレームワークは .NET Framework 3.5 にする必要があります。SharePoint カスタマイズ ウィザードで、デバッグ用のローカル Project Web App サイトを選択し、[ファーム ソリューションとして配置する] をクリックします。

  2. ListProjects PSI 拡張機能の WCF を使用するには、次の参照を追加します。

    • Microsoft.Office.Project.Server.Library

    • System.Runtime.Serialization

    • System.ServiceModel

  3. PSI 拡張機能へのサービス参照を追加し (https://localhost/pwa/_vti_bin/PSI/ListProjects.svc)、参照に名前を付けます (SvcListProjects など)。Project 2010 SDK ダウンロード内のサンプル ソリューションを使用している場合は、ソリューション エクスプローラーで [SvcListProjects] サービスを右クリックし、[サービス参照の更新] をクリックします。

  4. 新しい視覚的 Web パーツ アイテムを ListProjects プロジェクトに追加し、ListProjectsPart という名前を付けます。これにより、Web パーツとユーザー コントロールに必要なファイルと、アセンブリに署名するための厳密な名前のキーが作成されます。

  5. Elements.xml ファイル内で、Web パーツ グループの名前を設定します。たとえば、Group プロパティを "JS Grid Examples" に設定します。

    <?xml version="1.0" encoding="utf-8"?>
    <Elements xmlns="https://schemas.microsoft.com/sharepoint/" >
      <Module Name="ListProjectsPart" List="113" Url="_catalogs/wp">
        <File Path="ListProjectsPart\ListProjectsPart.webpart" 
               Url="ListProjectsPart.webpart" Type="GhostableInLibrary" >
          <Property Name="Group" Value="JS Grid Examples" />
        </File>
      </Module>
    </Elements>
    
  6. ListProjectsPart.webpart ファイル内で、Web パーツの Title プロパティと Description プロパティを設定します。

    <?xml version="1.0" encoding="utf-8"?>
    <webParts>
      <webPart xmlns="https://schemas.microsoft.com/WebPart/v3">
        <metaData>
          <type name="ListProjects.ListProjectsPart.ListProjectsPart, $SharePoint.Project.AssemblyFullName$" />
          <importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage>
        </metaData>
        <data>
          <properties>
            <property name="Title" type="string">List Projects with Custom Field Value</property>
            <property name="Description" type="string">Lists the projects that contain a specified custom field value.</property>
          </properties>
        </data>
      </webPart>
    </webParts>
    
  7. Feature1.feature デザイナーを開き、フィーチャーのタイトルと説明を編集します。たとえば、[タイトル] フィールドを "ListProjects フィーチャー" に変更し、[説明] フィールドを "ListProjects Web パーツは、指定のユーザー設定フィールド値を含むプロジェクトのリストを表示します" に変更します。

  8. Package.package デザイナーを開き、[名前] フィールドを、たとえば "ListProjects Web パーツ" に変更します。

ユーザー コントロールの変更

ListProjectsPartUserControl.ascx ファイルは視覚的 Web パーツ アイテムなので、デザイン ビューまたは分割ビューを使用して、ツールボックスからドラッグすることによっていずれかのウィンドウにコントロールを簡単に追加できます。ソース ビューでコントロールの要素および属性を入力することによって、コントロールを追加することもできます。

JS グリッド コントロールは、ECMAScript (JavaScript、JScript) コードを使用して、グリッドの機能と動作の管理、イベントへの添付、およびクライアント側でのグリッド コンテンツの操作を行います。JS グリッド コントロールはツールボックスにないため、これと、関連する GridManager 関数をコード ウィンドウ内で追加する必要があります (または、GridManager 関数を含む JavaScript ファイルへの参照を設定します)。詳細については、「JS グリッド コントロール実装のヒント」を参照してください。

手順 2. ListProjectsPartUserControl を変更するには

  1. ListProjectPartUserControl.ascx ファイルを開き、分割ビュー (図 1) を表示して、コード ウィンドウとデザイン ウィンドウの両方を表示します。

  2. ツールボックスからデザイン ウィンドウまたはコード ウィンドウの下部へ Label コントロールをドラッグします。ID 属性および Text 属性を次のように変更します。

    <asp:Label ID="LabelProjects" runat="server" 
    Text="Optics Program custom field value:  "></asp:Label>
    
  3. Textbox コントロールと改行用の Literal コントロールを追加します。以下に例を示します。

    <asp:TextBox ID="TextBoxCFValue" runat="server" 
    Tooltip="Type the Optics Program custom field value here"></asp:TextBox>
    <asp:Literal ID="Break1" runat="server"><br /></asp:Literal>
    
  4. Button コントロールをデザイン ウィンドウへドラッグし、ボタンの ID を ButtonListProjects に設定し、Text 値を List Projects に設定し、ボタンをダブルクリックします。Visual Studio によって作成される ButtonListProjects_Click イベント ハンドラーを使用すると、JS グリッド コントロールを初期化し、ListProjects サービスを呼び出して、グリッドのデータを取得できます。さらに 2 つの改行も追加して、ボタンと JS グリッド コントロールを離します。

    <asp:Button ID="ButtonListProjects" runat="server" Text="List Projects" 
        onclick="ButtonListProjects_Click" />
    <asp:Literal ID="Break2" runat="server"><br /><br /></asp:Literal>
    
  5. コード ウィンドウ内で以下を入力して、JS グリッド コントロールを追加します。

    <SharePoint:JSGrid ID="_grid" runat="server" /> 
    
  6. GridManager 関数を作成する JavaScript コードを追加します。次のどちらかの方法でコードを追加できます。

    • コードをインラインで追加します。たとえば、ListProjectsPartUserControl.ascx ファイル内で、script 要素内にコードを追加します。

      <script type="text/javascript">
          Type.registerNamespace("GridManager");
          GridManager = function () {
              this.Init = function (jsGridControl, initialData, props) {
                  var dataSource = new SP.JsGrid.StaticDataSource(initialData);
                  var jsGridParams = dataSource.InitJsGridParams();
                  jsGridControl.Init(jsGridParams);
              }
          };
      </script>
      
    • コードを追加する最良の方法は、SharePoint のマップされた Layouts フォルダー内の個別の .js ファイルにコードを追加する方法です。

      1. [ListProjects] プロジェクトを右クリックし、[追加] をクリックし、[SharePoint "レイアウト" のマップされたフォルダー] をクリックします。これにより、Layouts フォルダーと ListProjects サブフォルダーが作成されます。

      2. [Layouts]\[ListProjects] フォルダーを右クリックし、[追加] をクリックし、[新しい項目] をクリックします。[新しい項目の追加] ダイアログ ボックスの [インストールされているテンプレート] ウィンドウで、[Web] をクリックします。[JScript ファイル] をクリックし、「GridManager.js」という名前を入力し、[追加] をクリックします。

      3. GridManager.js ファイルを開き、次のコードをコピーします。

        Type.registerNamespace("GridManager");
        GridManager = function () {
            this.Init = function (jsGridControl, initialData, props) {
                var dataSource = new SP.JsGrid.StaticDataSource(initialData);
                var jsGridParams = dataSource.InitJsGridParams();
                jsGridControl.Init(jsGridParams);
            }
        };
        
      4. JS グリッド コントロールの別の関数を開発する予定の場合は、GridManager.js ファイルの先頭に次の行をコピーします。reference 要素によって、使用される共通の SharePoint 関数および JS グリッド コントロール関数に関する Intellisense 入力支援が実現されます。

        /// <reference path="~/_layouts/SP.core.debug.js"/>
        /// <reference path="~/_layouts/SP.debug.js"/>
        /// <reference path="~/_layouts/JSGrid.debug.js" />
        

        SharePoint Foundation、SharePoint Server、および Project Server 用の別の .js ファイルへの参照を追加できます。たとえば、[Program Files]\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS ディレクトリにある .js ファイル内の関数を検索します。

      5. ListProjectsPartUserControl.ascx ファイル内で、JSGrid コントロールを追加する行の前に次の行を追加します。

        <script type="text/javascript" src="~/_layouts/ListProjects/GridManager.js"></script>
        

        script 要素を閉じるには、/> ではなく、</script> 終了タグを使用する必要があります。

    図 1 の分割ビューでは、JS グリッド コントロールがデザイン ウィンドウで選択されています。[プロパティ] ウィンドウには、追加のグリッド プロパティが表示されます。この後の手順で、ソリューション エクスプローラー内の GridUtilities.cs ファイルおよび Deployment フォルダーを追加します。

    図 1. ListProjectsPartUserControl.ascx ファイルの分割ビュー

    ListProjects ユーザー コントロールの表示を分割する

  7. ユーザー コントロールの分離コード ファイル (ListProjectsPartUserControl.ascx.cs) を開き、必要な using ステートメントを追加します。以下に完全なリストを示します。

    using System;
    using System.IO;
    using System.Security.Principal;
    using System.ServiceModel;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    
    using System.Data;
    using Microsoft.SharePoint.JSGrid;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Utilities;
    using Microsoft.SharePoint.WebControls;
    using Microsoft.Office.Project.Server.Library;
    
  8. ListProjectsClient オブジェクトの WCF エンドポイントを設定するためのヘルパー メソッドを追加します。

    ListProjects Web パーツは Project Web App、PDP、またはプロジェクト サイトで実行する必要があるため、GetPwaSiteUrl メソッドはこの 3 つのどの状況でも Project Web App のベース URL を取得します。IsContextForActiveBrowsing メソッドは、HTTP コンテキストが、Internet Explorer のアクティブなブラウズ セッションに基づくかどうかを判断します。

    // Determine whether the HttpContext is for active browsing.
    private static bool IsContextForActiveBrowsing(HttpContext httpContext)
    {
        return httpContext != null && httpContext.User != null 
            && httpContext.Server != null;
    }
    
    // Get the base URL of Project Web App.
    private static string GetPwaSiteUrl(HttpContext httpContext)
    {
        if (IsContextForActiveBrowsing(httpContext))
        {
            // If the current site is a Project Web App site, return that.  
            SPWeb web = SPControl.GetContextWeb(httpContext);
            if (web.WebTemplateId == WSS.WssPWADefaultTemplateNumericId)
            {
                return httpContext.Request.Url.IsLoopback 
                    ? SPUrlUtility.CombineUrl(
                        httpContext.Request.Url.GetLeftPart(UriPartial.Authority),
                                                        web.Site.ServerRelativeUrl)
                    : web.Site.Url;
            }
    
            // If the current site is a project site, return the sponsoring 
            // Project Web App site.
            if (web.WebTemplateId >= WSS.WssPWSTemplateNumericIdMinLimit &&
                web.WebTemplateId <= WSS.WssPWSTemplateNumericIdMaxLimit)
            {
                return web.AllProperties["PWAURL"] as string;
            }
        }
        return null;
    }
    
  9. ヘルパー領域に SetClientEndpoints メソッドを追加します。Dispose メソッドを上書きして、DisposeClients メソッドを呼び出すようにします。

    private void SetClientEndpoints(string pwaUrl, bool isHttps)
    {
        const int MAXSIZE = 500000000;
    
        BasicHttpBinding binding = null;
    
        if (isHttps)
        {
            // Create a binding for HTTPS.
            binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
        }
        else
        {
            // Create a binding for HTTP.
            binding = new BasicHttpBinding(
                BasicHttpSecurityMode.TransportCredentialOnly);
        }
    
        binding.Name = "basicHttpConf";
        binding.SendTimeout = TimeSpan.MaxValue;
        binding.MaxReceivedMessageSize = MAXSIZE;
        binding.ReaderQuotas.MaxNameTableCharCount = MAXSIZE;
        binding.MessageEncoding = WSMessageEncoding.Text;
        binding.Security.Transport.ClientCredentialType = 
            HttpClientCredentialType.Ntlm;
    
        EndpointAddress addressListProjects = 
            new EndpointAddress(pwaUrl + SVCLISTPROJECTS_PATH);
    
        listProjectsClient = 
            new SvcListProjects.ListProjectsClient(binding, addressListProjects);
        listProjectsClient.ChannelFactory.Credentials.Windows.AllowedImpersonationLevel
            = TokenImpersonationLevel.Impersonation;
        listProjectsClient.ChannelFactory.Credentials.Windows.AllowNtlm = true;
    }
    
    public override void Dispose()
    {
        DisposeClients();
        base.Dispose();
    }
    
    // Dispose the service clients.
    public void DisposeClients()
    {
        listProjectsClient.Close();
    }
    
  10. ListProjects サービスと ListProjectsClient オブジェクトのクラスの定数を追加します。ListProjectsPartUserControl コンストラクターを追加します。コンストラクター内では、Project Web App URL を取得し、URL が HTTPS プロトコルを使用するかどうかを判断し、SetClientEndpoints を呼び出して SvcListProjects.ListProjectsClient オブジェクトを初期化します。

    private const string SVCLISTPROJECTS_PATH = "/_vti_bin/PSI/ListProjects.svc";
    
    private static string pwaUrl;
    private static SvcListProjects.ListProjectsClient listProjectsClient;
    
    public ListProjectsPartUserControl()
    {
        // Get the URL of Project Web App.
        HttpContext context = HttpContext.Current;
    
        // Get the base URL of Project Web App, for example, https://ServerName/pwa.
        pwaUrl = GetPwaSiteUrl(context);
    
        bool isHttps = pwaUrl.Contains("https");
        SetClientEndpoints(pwaUrl, isHttps);
    }
    
  11. Page_Load イベント ハンドラーでコントロールの全般的なプロパティを設定します。たとえば、JS グリッド コントロールの高さを 100 ピクセルに設定します。

    protected void Page_Load(object sender, EventArgs e)
    {
        _grid.Height = 100;
    }
    

構成用の Web パーツ プロパティの追加

ListProjects Web パーツで ListProjects PSI 拡張機能を呼び出すには、Microsoft SQL Server 名、レポート データベース (RDB) 名、ストアド プロシージャー名、およびストアド プロシージャーのパラメーターの名前を事前に構成する必要があります。これは視覚的 Web パーツなので、Web パーツのプロパティは既定のエディター パーツ コントロールに簡単に追加できます。

手順 3. Web パーツのプロパティを追加するには

  1. ListProjectsPartUserControl クラスで、Web パーツのプロパティの値を保持するクラス変数を追加します。HostWebPart という名前のプロパティを追加して、ListProjectsPart オブジェクトを格納します。cfValue 文字列は、テキスト ボックス コントロール内の値で設定されます。

    private static string sqlServerName = string.Empty;
    private static string rdbName = string.Empty;
    private static string sprocName = string.Empty;
    private static string sprocParamName = string.Empty;
    private static string cfValue = string.Empty;
    
    public ListProjectsPartHostWebPart { get; set; }
    
  2. ListProjectsPart.cs ファイル内で、既定の SQL Server 名とエディター パーツ内のプロパティ パネルの名前を表す定数を追加します。パブリック プロパティを追加し、ListProjectsPart コンストラクター内のプロパティを初期化します。コンストラクター内で、既定の Web パーツのサイズおよび表示形式も設定できます。

    各プロパティを装飾する属性によって、既定のエディター パーツに表示されるプロパティの設定、パーソナル化スコープの設定、およびエディター パーツ内のプロパティ パネルの値の設定が行われます。

    private const string DEFAULT_SERVER = "SERVER_NAME";
    private const string PROPERTY_PANEL_NAME = "List Projects Data Source";
    
    #region Web Part Properties
    [WebBrowsable(true), 
    Personalizable(PersonalizationScope.Shared), 
    WebDisplayName("SQL Server Name"), 
    WebDescription("Name of the SQL Server instance that includes the Reporting database."),
    SPWebPart.SPWebCategoryName(PROPERTY_PANEL_NAME)]
    public string SqlServerName { get; set; }
    
    [WebBrowsable(true),
    Personalizable(PersonalizationScope.Shared), 
    WebDisplayName("Reporting Database Name"), 
    WebDescription("Name of the Reporting database (RDB) for Project Server."),
    SPWebPart.SPWebCategoryName(PROPERTY_PANEL_NAME)]
    public string RdbName { get; set; }
    
    [WebBrowsable(true),
    Personalizable(PersonalizationScope.Shared), 
    WebDisplayName("Stored Procedure Name"), 
    WebDescription("Name of the stored procedure in the RDB that lists the projects."),
    SPWebPart.SPWebCategoryName(PROPERTY_PANEL_NAME)]
    public string SprocName { get; set; }
    
    [WebBrowsable(true), 
    Personalizable(PersonalizationScope.Shared), 
    WebDisplayName("SPROC Parameter Name"), 
    WebDescription("Name of the parameter for the custom field value in the stored procedure."),
    SPWebPart.SPWebCategoryName(PROPERTY_PANEL_NAME)]
    public string SprocParam { get; set; }
    
    # endregion
    
    public ListProjectsPart()
    {
        this.ChromeType = PartChromeType.TitleAndBorder;
        this.Height = 180;
    
        SqlServerName = DEFAULT_SERVER;
        RdbName = "ProjectServer_Reporting";
        SprocName = "ListProjectsInProgram";
        SprocParam = "@cfValue";
    }
    
  3. CreateChildControls メソッドで、視覚的 Web パーツという既定のコントロールの種類をユーザー コントロールの実際の種類に変更し、ListProjectPartUsercontrol.HostWebPart プロパティを初期化します。たとえば、Control control = Page.LoadControl(_ascxPath); を次のように変更します。

    protected override void CreateChildControls()
    {
        ListProjectsPartUserControl control = Page.LoadControl(_ascxPath) 
            as ListProjectsPartUserControl;
    
        if (control != null) control.HostWebPart = this;
    
        Controls.Add(control);
    }
    
  4. ListProjectsPartUserControl.ascx.cs ファイル内で、ListProjectsPartUserControl クラス内の OnPreRender イベント ハンドラーを上書きして、Web パーツのプロパティを ListProjectsPart ホストから設定します。ユーザーが Web パーツのプロパティを編集すると、ホストの Web パーツ内ではプロパティが変更されますが、ユーザー コントロール内の変更は明示的に設定する必要があります。

    // Set the Web Part custom properties.
    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);
    
        sqlServerName = HostWebPart.SqlServerName;
        rdbName = HostWebPart.RdbName;
        sprocName = HostWebPart.SprocName;
        sprocParamName = HostWebPart.SprocParam;
    }
    

最初の使用時における構成の要求

ListProjects Web パーツで ListProjects PSI 拡張機能を呼び出すには、SQL Server パラメーターの正しい値が設定されている必要があります。初期使用時に構成を要求するには、SQL Server 名が既定値の場合にエディター パーツを表示するハイパー リンク コントロールへの JavaScript 関数を追加します。ユーザーによって正しい SQL Server 名および他のプロパティ値が入力され、保存されると、値は SharePoint コンテンツ データベースに保存されます。以降の使用時に Web パーツの初期化用のハイパー リンク コントロールが表示されることはありません。

手順 4. Web パーツの最初の使用時に構成を要求するには

  • CreateChildControls メソッド (ListProjectsPart.cs ファイル) で、Controls.Add 行を次と置き換えます。

    if (this.SqlServerName == DEFAULT_SERVER)
    {
        HyperLink configLink = new HyperLink();
        string url = string.Format(
            "javascript:ShowToolPane2Wrapper('Edit', '129', '{0}');", this.ID);
    
        configLink.NavigateUrl = url;
        configLink.ID = string.Format("MsoFrameworkToolpartDefmsg_{0}", this.ID);
    
        string configText = string.Format(
            "<b>Click here to configure this Web Part:</b> see the <b>{0}</b> section.",
            PROPERTY_PANEL_NAME);
        configLink.Text = configText;
    
        Literal lineBreaks = new Literal();
        lineBreaks.ID = "LineBreak1";
        lineBreaks.Text = "<br /><br />";
        Controls.Add(configLink);
        Controls.Add(lineBreaks);
    }
    else
    {
        Controls.Add(control);
    }
    // Ensure that all child controls are set. Otherwise, because of the added ECMAScript 
    // command, you must click Apply twice in the editor part.
    EnsureChildControls();
    

JS グリッド コントロールの初期化

JS グリッド コントロールの列プロパティと行プロパティは GridUtilities クラスで設定されます。この記事の GridUtilities クラスは「[方法] 基本の JS グリッドを作成する」の例に基づいており、ProjectDataSet.Project テーブルの値の表示に固有の変更が加えられています。

手順 5. JS グリッド コントロールを初期化するには

  1. ListProjects プロジェクトにクラスを追加して、クラス ファイルに GridUtilities.cs という名前を付けます。

  2. GetGridColumns メソッドは SetColumnProperties メソッドを使用して、適切な列幅とわかりやすい列タイトルで、PROJ_UID プロパティ、PROJ_NAME プロパティ、PROJ_PROP_AUTHOR プロパティ、および PROJ_INFO_START_DATE プロパティのみを表示します。

    注意

    既定では、各列の IsSortable プロパティは true です。ただし、この例のコードは列の並べ替えを実装していません。既定では、IsHideable プロパティは true です。PROJ_NAME 列は、非表示にできないように設定されます。

    using System;
    using System.Collections.Generic;
    using System.Data;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.JSGrid;
    
    namespace ListProjects
    {
        public static class GridUtilities
        {
            // Get a collection of the grid columns.
            public static IList<GridColumn> GetGridColumns(DataTable table)
            {
                List<GridColumn> r = new List<GridColumn>();
    
                foreach (DataColumn iterator in table.Columns)
                {
                    // Specify which columns to show in the grid.
                    if (iterator.ColumnName == "PROJ_UID"
                            || iterator.ColumnName == "PROJ_NAME"
                            || iterator.ColumnName == "PROJ_PROP_AUTHOR"
                            || iterator.ColumnName == "PROJ_INFO_START_DATE")
                    {
                        GridColumn col = SetColumnProperties(iterator);
    
                        // Add the column.
                        r.Add(col);
                    }
                }
                return r;
            }
    
            // Set the column width, header name, and other properties.
            private static GridColumn SetColumnProperties(DataColumn dataCol)
            {
                GridColumn col = new GridColumn();
                col.FieldKey = dataCol.ColumnName;
    
                switch (col.FieldKey)
                {
                    case "PROJ_UID":
                        col.Name = "Project GUID";
                        col.Width = 256;
                        col.IsSortable = false;
                        break;
                    case "PROJ_NAME":
                        col.Name = "Project Name";
                        col.IsHidable = false;
                        col.IsSortable = true;
                        col.Width = 218;
                        break;
                    case "PROJ_PROP_AUTHOR":
                        col.Name = "Author";
                        col.IsHidable = true;
                        col.Width = 140;
                        break;
                    case "PROJ_INFO_START_DATE":
                        col.Name = "Start Date";
                        col.Width = 140;
                        break;
                    default:
                        col.Name = dataCol.ColumnName;
                        col.Width = 210;
                        break;
                }
                return col;
            }
    
        }
    }
    
  3. GetGridFields メソッドは、グリッド内の各列に対して書式設定されたフィールドを追加します。FormatGridField メソッドは、データの種類に基づいてフィールドのプロパティを設定します。文字列、日付、金額など、ローカライズ可能なフィールドの場合、FormatGridField メソッドは、値を変換するインラインの delegate メソッドを使用して GridField.Localizer プロパティを設定します。

    // Get a collection of the grid fields.
    public static IList<GridField> GetGridFields(DataTable table)
    {
        List<GridField> r = new List<GridField>();
    
        foreach (DataColumn iterator in table.Columns)
        {
            GridField field = new GridField();
            field = FormatGridField(field, iterator);
    
            r.Add(field);
        }
        return r;
    }
    
    // Match the propertyTypeId of the grid field with the column type.
    public static GridField FormatGridField(GridField gf, DataColumn dc)
    {
        // Set field key name.
        gf.FieldKey = dc.ColumnName;
    
        // When in doubt, serialize the data value.
        gf.SerializeDataValue = true; 
    
        if (dc.ColumnName != GridSerializer.DefaultGridRowStyleIdColumnName)
        {
            // Determine whether the field is timephased.
            if (dc.ColumnName.Substring(0, 5) == "Quarter")
            {
                // Ensure that the timephased column headers are 
                // always read-only, despite the grid settings.
                gf.EditMode = EditMode.ReadOnly;
            }
    
            // Add properties based on the type.
            if (dc.DataType == typeof(String))
            {
                gf.PropertyTypeId = "String";
    
                // The Localizer determines how to render the underlying data.
                gf.Localizer = (ValueLocalizer)delegate(DataRow row, object toConvert)
                {
                    return toConvert == null ? "" : toConvert.ToString();
                };
    
                // The Serialization type is a required property. 
                gf.SerializeLocalizedValue = true;
                gf.SerializeDataValue = false;
            }
            else if (dc.DataType == typeof(Int16)
                || dc.DataType == typeof(Int32) 
                || dc.DataType == typeof(Int64)
                || dc.DataType == typeof(Decimal)
                || dc.DataType == typeof(Double))
            {
                gf.PropertyTypeId = "JSNumber";
    
                // The Localizer determines how to render the underlying data.
                gf.Localizer = (ValueLocalizer)delegate(DataRow row, object toConvert)
                {
                    return toConvert == null ? "" : toConvert.ToString();
                };
    
                // The Serialization type is a required property.
                gf.SerializeLocalizedValue = true;
                gf.SerializeDataValue = false;
            }
            else if (dc.DataType == typeof(Hyperlink))
            {
                gf.PropertyTypeId = "Hyperlink";
                gf.Localizer = (ValueLocalizer)delegate(DataRow row, object toConvert)
                {
                    return toConvert == null ? "" : toConvert.ToString();
                };
                gf.SerializeLocalizedValue = false;
                gf.SerializeDataValue = true;
            }
            else if (dc.DataType == typeof(bool))
            {
                gf.PropertyTypeId = "CheckBoxBoolean";
                gf.SerializeDataValue = true;
                gf.SerializeLocalizedValue = false;
            }
            else if (dc.DataType == typeof(DateTime))
            {
                gf.PropertyTypeId = "JSDateTime";
                gf.Localizer = (ValueLocalizer)delegate(DataRow row, object toConvert)
                {
                    return toConvert == null ? "" : toConvert.ToString();
                };
                gf.SerializeDataValue = true;
                gf.SerializeLocalizedValue = true;
            }
            else if (dc.DataType == typeof(Guid))
            {
                gf.PropertyTypeId = "String";
                gf.Localizer = (ValueLocalizer)delegate(DataRow row, object toConvert)
                {
                    return toConvert == null ? "" : toConvert.ToString();
                };
                gf.SerializeDataValue = true;
                gf.SerializeLocalizedValue = true;
            }
            else
                throw new Exception("GridUtilities.FormatGridField: No PropertyTypeId is defined for this datatype: "
                    + dc.DataType.ToString());
        }
        return gf;
    }
    

    GUID プロパティは、文字列として単純に設定されます。カスタム プロパティの種類を作成することはできますが、それはこの記事の範囲を超えています。PropertyTypeId の有効な値は次のとおりです。

    • JSNumber

    • JSDateTime

    • String

    • CheckBoxBoolean

    • Hyperlink

  4. ListProjectsPartUserControl の分離コード ファイル内で、グリッドにデータを読み込んで GridManager.js ファイルで定義した GridManager 関数でグリッドを初期化するコードを、ButtonListProjects_Click イベント ハンドラーに追加します。

    ヒント

    JS グリッド コントロールを初期化および構成するコードを作成している場合は、グリッドが使用するデータを個別のファイルに保存しておくと簡単にテストできるので役立ちます。コメント アウトされたコードは、ProjectData4JSGrid.xml という名前のファイルを保存する方法を示しています。

    protected void ButtonListProjects_Click(object sender, EventArgs e)
    {
        cfValue = TextBoxCFValue.Text.Trim();
    
        if (cfValue != string.Empty)
        {
            SvcListProjects.ProjectDataSet projectDs =
                listProjectsClient.GetProjectsWithCustomFieldValue(
                    sqlServerName, rdbName, sprocName, sprocParamName, cfValue);
    
            _keyColumn = projectDs.Project.PROJ_UIDColumn.Caption;
    
            // If the directory does not exist, create it.
            // Assign the path where the output XML file will be saved.
            // Uncomment the following lines to create an XML file of the Project table.
    
            //if (!Directory.Exists(OUTPUT_FILES))
            //{
            //    Directory.CreateDirectory(OUTPUT_FILES);
            //}
            //string outFilePath = OUTPUT_FILES + "ProjectData4JSGrid.xml";
            //projectDs.Project.WriteXml(outFilePath);
    
            string[] fieldOrderColumns = { _keyColumn };
            FieldOrderCollection sortedColumns =
                new FieldOrderCollection(fieldOrderColumns);
    
            GridSerializer gds = new GridSerializer(SerializeMode.Full,
                projectDs.Project,
                _keyColumn,
                sortedColumns,
                GridUtilities.GetGridFields(projectDs.Project),
                GridUtilities.GetGridColumns(projectDs.Project));
    
            // Set the grid data serializer to the grid serializer object.
            _grid.GridDataSerializer = gds;
    
            // Tell the grid to listen to the GridManager controller.
            _grid.JSControllerClassName = "GridManager";
        }
    }
    

ListProjects Web パーツのテスト

Visual Studio 2010 では、Web パーツのデバッグは簡単です。.cs ファイルの 1 つにブレークポイントを設定し、F5 キーを押します。これにより、プロジェクトがコンパイルされ、グローバル アセンブリ キャッシュに ListProjects.dll がインストールされます。ListProjects プロジェクトの [サイトの URL] プロパティで指定されるサイトで Web パーツが展開およびアクティブ化され、Internet Explorer が開始し、正しい w3wp.exe プロセスおよび iexplore.exe プロセスに接続します。Web パーツまたは JS グリッド コントロールのデバッグの詳細な手順は、この記事の範囲を超えています。

Project Web App ページへの ListProjects の追加

ListProjects Web パーツは、Web パーツ ゾーンを含む任意の編集可能な Project Web App ページに追加できます。編集可能でないページの場合、[サイトの操作] メニューに [ページの編集] という項目はありません。

手順 6. Project Web App ページに ListProjects Web パーツを追加するには

  1. Project Web App で、[サイトの操作] をクリックし、[ページの編集] をクリックし、選択する Web パーツ ゾーンで [Web パーツの追加] をクリックします。図 2 は、Elements.xml ファイルに指定されているように、[List Projects with Custom Field Value] という Web パーツが [JS Grid Examples] グループに含まれていることを示しています。Web パーツのフレンドリ名は ListProjectsPart.webpart ファイルに指定されています。

    図 2. Project Web App のヘッダー ゾーンへの Web パーツの追加

    Header ゾーンに Web パーツを追加する

  2. Web パーツを構成します。ListProjects Web パーツを初めて実行するとき (図 3)、SQL Server Name プロパティには既定値が設定されており、構成に関するメッセージとエディター パーツへのハイパーリンクが表示されます。エディター パーツ内の "List Projects Data Source" というパネル名は、ListProjectsPart.cs ファイル内の PROPERTY_PANEL_NAME 定数によって指定されています。

    図 3. 最初の実行時の Web パーツの構成

    初回実行時に Web パーツを構成する

  3. SQL Server 名のフィールドに、レポート データベースが配置される Microsoft SQL Server インストールの名前を入力します。[List Projects Data Source] パネル内の他のフィールドが正しいことを確認し、[OK] をクリックします。

データ ソースの正しいプロパティ値を保存すると、そのプロパティは OnPreRender イベント ハンドラーに設定され、更新されて、ListProjectsPartUserControl.ascx ファイルに追加した子コントロールが表示されます。最後に、ユーザー設定フィールド値に一致する値を入力し、Enter キーを 2 回押すと、そのユーザー設定フィールド値を持つプロジェクトのリストが表示されます (図 4)。たとえば、テキスト ボックスに「Optical Fabrication」と入力します。

カスタム Web パーツのプロパティは SharePoint コンテンツ データベースに保存されるため、以降の実行では、ListProjects Web パーツは、構成のハイパー リンク コントロールではなく、ラベル、テキスト ボックス、ボタン、および JS グリッド コントロールを表示します。構成コントロールを再び表示するには、Web パーツを編集して、SQL Server 名のフィールドを SERVER_NAME に戻します。ページ上で Web パーツを削除し、それを再び追加した場合も、既定のプロパティ値が設定されます。

注意

図 4 は、列の並べ替えを実装している Project 2010 SDK ダウンロード内の ListProjects Web パーツ サンプルの結果を示しています。この記事の ListProjects サンプルの場合、[Project Name] 列をクリックすると、[列の構成] オプションのみが表示されます。他の列の見出しをクリックした場合、オプションには [列を表示しない] も含まれます。

図 4. Project Web App ページ内での ListProjects Web パーツの使用

Project Web App で ListProjects Web パーツを使用する

列見出しをクリックし、[列の構成] をクリックすると、JS グリッド コントロールは [列の構成] モーダル ダイアログ ボックス (図 5) を表示します。GridUtilities.SetColumnProperties メソッドで IsHidable プロパティが false に設定されているので、[Project Name] 列を非表示にすることはできません。

図 5. JS グリッド列の構成

JS Grid 列を構成する

ListProjects Web パーツの展開

Internet Explorer を閉じるか、Visual Studio で Shift + F5 キーを押すと、Web パーツが取り消され、IIS がリセットされます (ListProjects プロパティ ページの [SharePoint] タブで [デバッグ後に自動取り消し] チェック ボックスがオンの場合)。[ビルド] メニューの [ソリューションの展開] をクリックすると、ソリューションが開発用コンピューターに展開され、Visual Studio から独立して Web パーツを使用できます。

SharePoint ソリューション パッケージ (.wsp ファイル) を作成することによって、ListProjects Web パーツをテスト コンピューターや他の Project Server コンピューターに展開することもできます。手順 7. の DeployListProject.cmd ファイルと DeploySolution.ps1 ファイルは、「Microsoft Project 2010 Solution Starters (英語)」の展開ファイルに基づいています。

手順 7. List Projects Web パーツを展開するには

  1. Visual Studio で、[ビルド] メニューの [パッケージ] をクリックします。pkg サブディレクトリにインストール パッケージがビルドされ、bin\Debug サブディレクトリに ListProjects.wsp ファイルが作成されます。ListProjects.wsp ファイルは実際には .cab 形式のファイルなので、WinZip.exe を使用してファイルを開き、内容を確認できます。

  2. ソリューション エクスプローラーで、展開ファイルを格納するためのフォルダーを作成します。たとえば、ListProjects プロジェクト ノードに Deployment という名前のフォルダーを追加します。ListProjects.wsp ファイルを Deployment フォルダーにコピーします。

  3. Deployment フォルダーに DeployListProjects.cmd ファイルを作成し、次のスクリプトをコピーします。SiteUrl の値は各自の Project Web App URL に変更します。

    @echo off
    Set DeploymentPackageFolder="."
    
    Set SiteUrl="https://ServerName/ProjectServerName"
    Set SolutionFolder="./"
    Set SolutionName="ListProjects.wsp"
    Set FeatureName="ListProjects_Feature1"
    
    cd %DeploymentPackageFolder%
    powershell "& set-executionpolicy remotesigned"
    PowerShell -file .\DeploySolution.ps1 %SiteUrl% %SolutionFolder% %SolutionName% %FeatureName%
    
    pause
    
  4. DeploySolution.ps1 ファイルを作成し、次の Windows PowerShell コマンドをコピーします。

    $SiteUrl = $args[0]
    $SolutionFolder = $args[1]
    $SolutionName = $args[2]
    $FeatureName = $args[3]
    
    $AdminServiceName = "SPAdminV4"
    $IsAdminServiceRunning = $true;
    
    
    Add-PSSnapin microsoft.sharepoint.powershell
    
    if ($(Get-Service $AdminServiceName).Status -eq "Stopped")
    {
        $IsAdminServiceRunning = $false;
        Start-Service $AdminServiceName       
    }
    
    $SingleSiteCollection = Get-SPSite $SiteUrl
    
    Write-Host
    
    if ($FeatureName -ne $null)
    {
        Write-Host "Deactivating feature: $FeatureName" -NoNewline
            $WebAppsFeatureId = $(Get-SPFeature -limit all | ? {($_.displayname -eq $FeatureName)}).Id
            if (($WebAppsFeatureId -ne $null) -and ($SingleSiteCollection.Features | ? {$_.DefinitionId -eq $WebAppsFeatureId}))
            {
                Disable-SPFeature $FeatureName -Url $SiteUrl -Confirm:$false
            }
        Write-Host " - Done."
    }
    
    Write-Host "Rectracting solution: $SolutionName" -NoNewline
        $Solution = Get-SPSolution | ? {($_.Name -eq $SolutionName) -and ($_.Deployed -eq $true)}
        if ($Solution -ne $null)
        {
            if($Solution.ContainsWebApplicationResource)
            {
                Uninstall-SPSolution $SolutionName -AllWebApplications -Confirm:$false
            }
            else
            {
                Uninstall-SPSolution $SolutionName -Confirm:$false
            }
        }
    
        while ($Solution.JobExists)
        {
            Start-Sleep 2
        }
    Write-Host " - Done."
    
    Write-Host "Removing solution: $SolutionName" -NoNewline
        if ($(Get-SPSolution | ? {$_.Name -eq $SolutionName}).Deployed -eq $false)
        {
            Remove-SPSolution $SolutionName -Confirm:$false
        } 
    Write-Host " - Done."
    Write-Host
    
    Write-Host "Adding solution: $SolutionName" -NoNewline
        $SolutionPath = $SolutionFolder + $SolutionName
        Add-SPSolution $SolutionPath | Out-Null
    Write-Host " - Done."
    
    Write-Host "Deploying solution: $SolutionName" -NoNewline
        $Solution = Get-SPSolution | ? {($_.Name -eq $SolutionName) -and ($_.Deployed -eq $false)}
        if(($Solution -ne $null) -and ($Solution.ContainsWebApplicationResource))
        {
            Install-SPSolution $SolutionName -AllWebApplications -GACDeployment -Confirm:$false
        }
        else
        {
            Install-SPSolution $SolutionName -GACDeployment -Confirm:$false
        }
        while ($Solution.Deployed -eq $false)
        {
            Start-Sleep 2
        }
    Write-Host " - Done."
    
    if (-not $IsAdminServiceRunning)
    {
        Stop-Service $AdminServiceName     
    }
    Echo Finished
    
  5. 管理者としてコマンド プロンプト ウィンドウを開き、DeployListProjects.cmd を実行します。Windows PowerShell の実行ポリシーが設定され、DeploySolution.ps1 ファイルが実行されます。

SharePoint ソリューションの詳細については、「SharePoint 2010 へのファーム ソリューションのインストールと展開」を参照してください。

プロジェクト詳細ページへの ListProjects の追加

PDP に Web パーツを追加する手順は、別の Project Web App ページに Web パーツを追加する手順と基本的に同じです。

手順 8. PDP に ListProjects Web パーツを追加するには

  1. PDP を編集するには、Project Web App の [サーバー設定] ページを開き、[ワークフローおよびプロジェクト詳細ページ] セクションの [プロジェクト詳細ページ] をクリックして、PDP ページのライブラリを表示します。

    注意

    Project Web App ページと PDP では、Project Server アセンブリ、プロジェクト コンテキスト データ、および Microsoft SharePoint Designer 2010 がサポートしない他の機能を使用するため、SharePoint Designer でページを編集できません。したがって、PDP ライブラリ内のページを選択し、[ライブラリ ツール] の [ドキュメント] タブの [ドキュメントの編集] をクリックすると、SharePoint Designer には [Web サイトの編集が無効です] ダイアログ ボックスが表示されます。

  2. ライブラリ内の PDP 名をクリックします。たとえば、[プロジェクト情報] をクリックすると、プロジェクト情報のページが表示されます。前述のように、ページの [サイトの操作] メニューを使用して、ページを編集できます。

  3. 編集されたプロジェクト情報 PDP を使用するには、Project Web App の [プロジェクト センター] ページで [新規] をクリックし、[サンプル提案] をクリックします。サンプル提案のワークフローは、プロジェクト情報 PDP を示します (図 6)。

    図 6. プロジェクト情報 PDP 内での ListProjects Web パーツの使用

    PDF で ListProjects Web パーツを使用する

プロジェクト サイト ページへの ListProjects の追加

ListProjectsPartUserControl クラスの GetPWASiteUrl メソッドは、プロジェクト サイトのスポンサーとなる Project Web App サイトの URL を返すことができるため、プロジェクト サイトに同じ ListProjects Web パーツを追加できます (図 7)。SetClientEndpoints メソッドにおいて、ListProjects PSI 拡張機能の EndpointAddress は、Project Web App のベース URL を含みます。

プロジェクト サイトに Web パーツを追加する手順は前述の手順と同じで、ページの [サイトの操作] メニューを使用します。

図 7. プロジェクト サイト内での ListProjects Web パーツの使用

プロジェクト サイトで ListProjects Web パーツを使用する

ASP.NET フレームワークに基づいて構築された Web パーツは、PSI 拡張機能に加えて、組み込みの PSI サービスを使用できます。WCF エンドポイント アドレスを正しく設定することにより、Project Web App ページ、プロジェクト詳細ページ、およびプロジェクト サイトに同じ Web パーツを追加できます。

次の手順

JS グリッド コントロールでは、機能によっては (列の並べ替えなど)、JavaScript を使用してコールバック デリゲートを設定し、Microsoft Visual C# または Visual Basic を使用してコールバックを実装する必要があるため、そのプログラミングは複雑になります。しかし、JS グリッド コントロールには、柔軟性に優れ、サーバーへのポストバックを必要とせずに多くの機能を実行できるという、他のグリッド コントロールにはないメリットがあります。列の並べ替えを実装した ListProjects Web パーツの完全なソリューションについては、Project 2010 SDK ダウンロード内の Samples\WebParts\ListProjects_Sorting サブディレクトリを参照してください。

JS グリッド コントロールには、この他にも、Web パーツの価値を高める多くの機能があります。JS グリッド コントロール内でのイベントの使用の詳細については、「チュートリアル : PWA リボンのカスタマイズと JS グリッドのアクセス」を参照してください。詳細については、SharePoint 2010 SDK の「JS グリッド コントロール」を参照してください。

関連項目

タスク

[方法] RDB のユーザー設定フィールドを読み取る PSI 拡張を作成する方法

チュートリアル : PWA リボンのカスタマイズと JS グリッドのアクセス

その他のリソース

Project Server Web パーツの開発

JS グリッド コントロール

JS グリッド コントロール実装のヒント

[方法] 基本の JS グリッドを作成する

Microsoft Project 2010 Solution Starters (英語)

Developing Custom Solutions in PWA (英語)

User Interface Customization Resource Center | SharePoint 2010 (英語)