複数列ルックアップを作成する

最終更新日: 2010年12月1日

適用対象: SharePoint Foundation 2010

Microsoft SharePoint Foundation では、ルックアップ列は、他のリストの列の値を表示するように構成された列です。ユーザーは新しい項目を作成するとき、ルックアップ列には値を入力せず、他のリストの列のドロップダウン リストから値を選択します。SharePoint Foundation 2010 では、複数列ルックアップを作成できます。このルックアップでは、プライマリ ルックアップ列によってターゲット リストの項目が選択され、1 つ以上のセカンダリ ルックアップ列には、同じリスト項目の他の列の値が表示されます。

ルックアップ列のターゲットのフィールド型は、Counter、DateTime、Number、Text のいずれかにすることができます。これらのフィールド型の詳細については、SPFieldType 列挙を参照してください。さらに、出力がテキストの場合は、Calculated フィールド型をターゲットにできます。詳細については、SPFieldCalculated クラスの OutputType プロパティを参照してください。フィールドに対してルックアップが有効になっている場合は、Computed フィールド型をターゲットにできます。詳細については、SPFieldComputed クラスの EnableLookup プロパティを参照してください。

複数列ルックアップを作成する方法は、新しいリストの列を定義するか既存のリストに列を追加するかによって異なりますが、どちらの場合も、大抵はフィーチャーとの関連で列を作成します。フィーチャーの実装の詳細については、「フィーチャーの使用」を参照してください。

新しいリストにルックアップ列を作成する

ルックアップ列をリストに作成し、さらに、その列を同じフィーチャーの一部として作成するとき、宣言型 XML を記述して列とリストを定義するのが最も簡単です。Microsoft Visual Studio 2010 の SharePoint 開発者ツールには、ユーザーに代わって処理を行うためのテンプレートが複数用意されています。また、テンプレートにより、フィーチャー用のソリューション パッケージがビルドされ、F5 キーを押すと自動的に展開されます。また、デバッグを停止すると、ソリューションが取り消されます。これにより、繰り返し処理の多い開発が非常に実行しやすくなります。

プライマリおよびセカンダリ ルックアップ列は、新しいリストの定義の一部として (つまり、リスト スキーマの一部として) 定義できます。ただし、最適なのは、サイト列を作成し、その列をサイト コンテンツ タイプに含めて、コンテンツ タイプを新しいリストのベースとして使用することです。この方法を利用すると、他のリストの列を使用できるので、再利用性が向上します。また、列定義を、リスト定義とは別に管理したり更新したりすることもできます。

始める前に、ルックアック列のターゲットになるリストの情報を収集する必要があります。まず、ターゲット リストを識別する方法を知っておかなければなりません。他の列と同様、ルックアップ列は XML 列の Field 要素によって定義されます。ルックアップ列のターゲット リストは、Field 要素の List 属性の値によって識別されます。属性値は、リスト ID (GUID) または Web 相対 URL のどちらかにできます。2 つ目のオプションである Web 相対 URL は、ターゲット リストが存在しない場合にのみ動作します。この場合、ターゲット リストは、ルックアップ列を作成するフィーチャーと同じフィーチャーに作成する必要があります。

ターゲット リストが既に存在する場合は、そのターゲット リストの ID を取得します。それには、そのリストを表す SPList オブジェクトへの参照を取得する単純なコンソール アプリケーションを作成し、ID プロパティの値をそのコンソールに出力します。必要な値は、System.Guid クラスの ToString("B") メソッドによって返されます。

using (SPSite site = new SPSite("http://localhost"))
{
    using (SPWeb web = site.RootWeb)
    {
        SPList list = web.Lists.TryGetList("Contoso Cutomers");
        if (list != null)
            Console.WriteLine(list.ID.ToString("B"));
    }
}

Microsoft SharePoint Designer 2010 を使用して ID を取得することもできます。Web サイトを開き、ナビゲーション ウィンドウで [リストとライブラリ] を選択し、リストの名前を右クリックして [リストの設定] を選択します。[リスト情報] の [リスト ID] を検索し、GUID 全体 (波かっこを含む) をコピーします。

さらに、ルックアップ フィールドの 1 つが参照するターゲット リストの各フィールドの内部名が必要です。内部名は Field 要素の Name 属性の値 (フィールド定義を調べている場合)、または SPField オブジェクトの InternalName プロパティによって返される値 (コードを記述して情報を収集している場合) です。

ヒントヒント

組み込み列の内部名については、SPBuiltInFieldId クラスのドキュメントを参照してください。このクラスの各フィールドの名前が組み込み列の内部名です。たとえば、[作成者] フィールドの内部名は Created_x0020_By です。

一般的に、新しいリストに複数列ルックアップを作成するには、次の作業を行う必要があります。

  1. ルックアップ列をサイト列として定義します。

  2. ルックアップ列を使用するコンテンツ タイプを定義します。

  3. 新しいコンテンツ タイプに基づいて、リストおよびリスト インスタンスを定義します。

  4. フィーチャーを展開、アクティブ化、およびテストします。

ルックアップ列をサイト列として定義するには

  1. Visual Studio 2010 で、SharePoint 2010 の [空の SharePoint プロジェクト] テンプレートを使用して、新しいプロジェクトを作成します。

  2. SharePoint カスタマイズ ウィザードで [サンドボックス ソリューションとして配置する] を選択し、[完了] をクリックします。

  3. ソリューション エクスプローラーで [Features] フォルダーを右クリックし、[フィーチャーの追加] を選択します。

    フィーチャー デザイナーが表示されます。ここで、タイトルと説明を編集し、フィーチャーの範囲を選択することができます。このアプリケーションに適したフィーチャーの範囲は Web または Site のどちらかです。詳細については、「要素の範囲」を参照してください。

  4. (オプション) ルックアップのターゲット リストを作成します。

    カスタム リスト定義からターゲット リストを作成するには、「[方法] カスタム リスト定義を作成する」で説明されている手順に従ってください。既存のリストからターゲット リストを作成するには、次の手順に従います。

    1. ソリューション エクスプローラーでプロジェクトを選択し、[プロジェクト] メニューで [新しいアイテムの追加] を選択します。

    2. [新しいアイテムの追加] ダイアログ ボックスで [リスト インスタンス] テンプレートを選択し、リストの名前を入力します。[追加] をクリックします。

    3. SharePoint カスタマイズ ウィザードのプロンプトに従います。

      ウィザードでは、リスト テンプレートを選択し、リストの URL を指定するように求められます。

  5. プライマリ ルックアップ列のフィールド定義を作成します。

    1. ソリューション エクスプローラーでプロジェクトをクリックし、[プロジェクト] メニューで [新しいアイテムの追加] を選択します。

    2. [新しいアイテムの追加] ダイアログ ボックスで [空の要素] テンプレートを選択し、要素の名前 ("SiteColumns" など) を入力して、[追加] をクリックします。

      Visual Studio では、プロジェクトに追加するフォルダーの名前として入力した名前が使用されます。Visual Studio によって、フォルダー内に Elements.xml という名前のファイルが作成されます。

    3. Elements.xml で、次の XML を Elements 要素内に挿入します。

      <!-- Primary lookup column -->
      <Field Type="Lookup" Name="" ID="" List="" ShowField="" DisplayName="" Required="" Group="" />
      
    4. Name 属性の値を入力します。

      これはフィールドの内部名です。この名前は、このフィールドが作成される Web サイトの AvailableFields プロパティによって返されるコレクション内で一意にする必要があります。一意性を保証するために、SharePoint Foundation によって必要に応じて値が追加されます。

    5. Visual Studio で、[ツール] メニューで [GUID の作成] を選択します。[GUID の作成] ダイアログ ボックスで [レジストリ形式] を選択し、[コピー]、[終了] の順にクリックします。

      新しい GUID をクリップボードにコピーします。

    6. 新しい GUID (波かっこを含む) を引用符で囲むように貼り付けて、ID 属性の値を指定します。

    7. List 属性の値を指定します。

      List 属性により、ルックアップ列のターゲット リストが識別されます。このリストが既に存在する場合、値はリスト ID、つまり GUID (波かっこを含む) です。

      ターゲット リストが存在しない場合は、Web 相対 URL (Lists/Contoso Customers など) を List 属性の値として使用できます。ただし、ルックアップ列を作成する同じフィーチャーの一部として、リストを作成する必要があります (手順 4. を参照)。ターゲット リストを作成する ListInstance 要素の Url 属性の値を使用してください。

    8. ShowField 属性の値を指定します。

      ShowField 属性の値は、List 属性で識別されるリストのターゲット フィールドの内部名です。

    9. DisplayName 属性の値を指定します。

      これはリスト ビューとフォームの列に表示される名前で、最大長は 255 文字です。値は $Resources:String 書式のローカライズされたリソースへの参照にできます。詳細については、「SharePoint ソリューションのローカライズ」を参照してください。

    10. Required 属性を true または false に設定します。

      リスト項目の New または Edit フォームを入力しているユーザーが必ずフィールドに対して値を選択するようにする場合は true を指定します。フィールドを空にできるようにする場合は false を指定します。

    11. (オプション) Group 属性の値を指定します。

      Group 属性では、列が Site Columns ギャラリーに表示されるときに、その列を配置するグループの名前が指定されます。その名前のグループが存在しない場合は、作成されます。作成する列のグループを定義すると、列が管理しやすくなります。

  6. セカンダリ ルックアップ列のフィールド定義を作成します。

    1. Elements.xml で、次の XML を Elements 要素内に挿入します。

      <!-- Secondary lookup column -->
      <Field Type="Lookup" FieldRef="" Name="" ID="" List="" ShowField="" DisplayName="" Required="" Group="" ReadOnly="TRUE" />
      
    2. FieldRef 属性の値を指定します。

      この属性は、プライマリ ルックアップ列のフィールド定義を参照します。プライマリ ルックアップの ID 属性の値を使用してください。ただし、波かっこは省略します。

    3. 手順 5. に従って、残りの属性の値を指定します。

  7. 手順 6. を必要な分だけ繰り返して、フィーチャーの残りのセカンダリ ルックアップ列ごとにフィールド定義を作成します。

この時点で、フィールド定義は次の例のようになります。この例では、Contoso Customer リストへの複数列ルックアップを定義します。

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!-- Primary lookup column: CustIDLookup -->
  <Field Type="Lookup" 
         Name="CustIDLookup" 
         ID="{2A670022-84AF-4C51-84F7-8E1B6025F104}" 
         List="Lists/Contoso Customers" 
         ShowField="ID" 
         DisplayName="Customer ID" 
         Required="true" 
         Group="Contoso Columns"/>
  <!-- Secondary lookup column: CustFirstNameLookup -->
  <Field Type="Lookup" 
         FieldRef="2A670022-84AF-4C51-84F7-8E1B6025F104" 
         Name="CustFirstNameLookup" 
         ID="{F0AF2CA5-EA71-46F7-9536-036539BA8C5C}" 
         List="Lists/Contoso Customers" 
         ShowField="FirstName" 
         DisplayName="First Name" 
         Required="false" 
         Group="Contoso Columns" 
         ReadOnly="TRUE" />
  <!-- Secondary lookup column: CustLastNameLookup -->
  <Field Type="Lookup" 
         FieldRef="2A670022-84AF-4C51-84F7-8E1B6025F104" 
         Name="CustLastNameLookup" 
         ID="{1D7973CE-49CD-46BD-9355-81014246578D}" 
         List="Lists/Contoso Customers" 
         ShowField="Title" 
         DisplayName="Last Name" 
         Required="false" 
         Group="Contoso Columns" 
         ReadOnly="TRUE" />
  <!-- Secondary lookup column: CustPhoneLookup -->
  <Field Type="Lookup" 
         FieldRef="2A670022-84AF-4C51-84F7-8E1B6025F104" 
         Name="CustPhoneLookup" 
         ID="{0F51E81B-2001-4A52-B33A-0F401814118B}" 
         List="Lists/Contoso Customers" 
         ShowField="HomePhone" 
         DisplayName="Phone" 
         Required="false" 
         Group="Contoso Columns" 
         ReadOnly="TRUE" />
</Elements>

サイト コンテンツ タイプを定義するには

  1. ソリューション エクスプローラーでプロジェクトをクリックし、[プロジェクト] メニューで [新しいアイテムの追加] を選択します。

  2. [新しいアイテムの追加] ダイアログ ボックスで [コンテンツ タイプ] テンプレートを選択し、コンテンツ タイプの名前 ("CustomerOrder" など) を入力して、[追加] をクリックします。

    [コンテンツ タイプ設定の選択] ダイアログ ボックスが表示されます。

  3. 継承元の基本コンテンツ タイプを選択します。[完了] をクリックします。

    Visual Studio では、プロジェクトに追加するフォルダーの名前として入力した名前が使用されます。フォルダー内には、Elements.xml という名前のファイルがあります。ここで、コンテンツ タイプを定義します。

  4. エディターで Elements.xml を開きます。

    注意

    ファイルに Elements 要素が含まれ、その要素に ContentType 要素が含まれ、さらにその要素に FieldRef 要素が含まれている場合は、適切なファイルが開きます。

  5. (オプション) Visual Studio によって、ContentType 要素の Inherits 属性が TRUE に設定されます。表示名を変更するなど、継承されたフィールドの特性を上書きする場合は、Inherits 属性の値を FALSE に設定します。

  6. 次の XML を FieldRefs 要素内に貼り付けて、プライマリ ルックアップ列を参照します。

    <FieldRef ID="" Name="" DisplayName="" Required=""/>
    
  7. ID 属性と Name 属性を、プライマリ ルックアップ列を定義する Field 要素の属性と同じ値に設定します。

    ID 属性では大文字と小文字が区別されるので、Field 要素の値をそのまま正確にコピーします。波かっこも忘れないようにしてください。

  8. DisplayName 属性および Required 属性の値を指定します。

  9. セカンダリ ルックアップ列ごとに、手順 6. ~ 8. を繰り返します。

  10. 特性を変更する継承された列ごとに、手順 6. ~ 8. を繰り返します。

    詳細については、「[方法] コンテンツ タイプ内の列を参照する」を参照してください。

完成したコンテンツ タイプ定義は次の例のようになります。

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!-- Parent ContentType: Item (0x01) -->
  <ContentType ID="0x0100b4160be88d9a4d669f690459bdcf43ff"
               Name="Contoso - Order"
               Group="Contoso Content Types"
               Description="Represents a customer order"
               Inherits="FALSE"
               Version="0">
    <FieldRefs>
      <FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" DisplayName="Description" Required="TRUE"/>
      <FieldRef ID="{bc91a437-52e7-49e1-8c4e-4698904b2b6d}" Name="LinkTitleNoMenu" DisplayName="Description" ReadOnly="TRUE" />
      <FieldRef ID="{82642ec8-ef9b-478f-acf9-31f7d45fbc31}" Name="LinkTitle" DisplayName="Description" ReadOnly="TRUE"/>
      <FieldRef ID="{2A670022-84AF-4C51-84F7-8E1B6025F104}" Name="CustIDLookup" DisplayName="Customer ID" Required="TRUE"/>
      <FieldRef ID="{F0AF2CA5-EA71-46F7-9536-036539BA8C5C}" Name="CustFirstNameLookup" DisplayName="First Name" Required="FALSE"/>
      <FieldRef ID="{1D7973CE-49CD-46BD-9355-81014246578D}" Name="CustLastNameLookup" DisplayName="Last Name" Required="FALSE"/>
      <FieldRef ID="{0F51E81B-2001-4A52-B33A-0F401814118B}" Name="CustPhoneLookup" DisplayName="Phone" Required="FALSE"/>
    </FieldRefs>
  </ContentType>
</Elements>

リストおよびリスト インスタンスを定義するには

  1. ソリューション エクスプローラーでプロジェクトをクリックし、[プロジェクト] メニューで [新しいアイテムの追加] を選択します。

  2. [新しいアイテムの追加] ダイアログ ボックスで [コンテンツ タイプからのリスト定義] テンプレートを選択し、リストの名前 (OrdersListDefinition など) を入力して、[追加] をクリックします。

    [リスト定義の設定の選択] ダイアログ ボックスが表示されます。

  3. ルックアップ列が含まれるコンテンツ タイプを選択し、[このリスト定義のリスト インスタンスを追加する] チェック ボックスをオンにして、[完了] をクリックします。

    Visual Studio では、プロジェクトに追加するフォルダーの名前として入力した名前が使用されます。フォルダー内には、ListTemplate 要素が含まれる Elements.xml という名前のファイルと List 要素が含まれる Schema.xml という名前のファイル、および ListInstance 要素を持つ別の Elements.xml ファイルが含まれる ListInstance1 という名前のフォルダーがあります。

  4. Schema.xml ファイルを開きます。

    ContentTypes 要素にはコンテンツ タイプ定義のコピーが、Fields 要素にはルックアップ列のフィールド定義のコピーが含まれていることに注意してください。

    Views 要素までスクロールします。2 つのビューが定義されているのに、どちらのビューにも、ルックアップ列を参照する FieldRef 要素が含まれていないことに注意してください。

  5. リスト ビューでレンダリングする任意の列の FieldRef 要素をコピーして、ビューの定義の ViewFields 要素内に貼り付けます。

    ViewFields 要素内の FieldRef 要素では、ID 属性および Name 属性のみが必要です。

Schema.xml ファイルの Views 要素は次の例のようになります。

<Views>
  <View BaseViewID="0" Type="HTML" MobileView="TRUE" TabularView="FALSE">
    <Toolbar Type="Standard" />
    <XslLink Default="TRUE">main.xsl</XslLink>
    <RowLimit Paged="TRUE">30</RowLimit>
    <ViewFields>
      <FieldRef Name="LinkTitleNoMenu"></FieldRef>
      <FieldRef ID="{2A670022-84AF-4C51-84F7-8E1B6025F104}" Name="CustIDLookup" />
      <FieldRef ID="{F0AF2CA5-EA71-46F7-9536-036539BA8C5C}" Name="CustFirstNameLookup" />
      <FieldRef ID="{1D7973CE-49CD-46BD-9355-81014246578D}" Name="CustLastNameLookup"  />
      <FieldRef ID="{0F51E81B-2001-4A52-B33A-0F401814118B}" Name="CustPhoneLookup" />
    </ViewFields>
    <Query>
      <OrderBy>
        <FieldRef Name="Modified" Ascending="FALSE">
        </FieldRef>
      </OrderBy>
    </Query>
    <ParameterBindings>
      <ParameterBinding Name="AddNewAnnouncement" Location="Resource(wss,addnewitem)" />
      <ParameterBinding Name="NoAnnouncements" Location="Resource(wss,noXinviewofY_LIST)" />
      <ParameterBinding Name="NoAnnouncementsHowTo" Location="Resource(wss,noXinviewofY_ONET_HOME)" />
    </ParameterBindings>
  </View>
  <View BaseViewID="1" Type="HTML" WebPartZoneID="Main" DisplayName="$Resources:core,objectiv_schema_mwsidcamlidC24;" DefaultView="TRUE" MobileView="TRUE" MobileDefaultView="TRUE" SetupPath="pages\viewpage.aspx" ImageUrl="/_layouts/images/generic.png" Url="AllItems.aspx">
    <Toolbar Type="Standard" />
    <XslLink Default="TRUE">main.xsl</XslLink>
    <RowLimit Paged="TRUE">30</RowLimit>
    <ViewFields>
      <FieldRef Name="Attachments">
      </FieldRef>
      <FieldRef Name="LinkTitle">
      </FieldRef>
      <FieldRef ID="{2A670022-84AF-4C51-84F7-8E1B6025F104}" Name="CustIDLookup" />
      <FieldRef ID="{F0AF2CA5-EA71-46F7-9536-036539BA8C5C}" Name="CustFirstNameLookup" />
      <FieldRef ID="{1D7973CE-49CD-46BD-9355-81014246578D}" Name="CustLastNameLookup"  />
      <FieldRef ID="{0F51E81B-2001-4A52-B33A-0F401814118B}" Name="CustPhoneLookup" />
    </ViewFields>
    <Query>
      <OrderBy>
        <FieldRef Name="ID">
        </FieldRef>
      </OrderBy>
    </Query>
    <ParameterBindings>
      <ParameterBinding Name="NoAnnouncements" Location="Resource(wss,noXinviewofY_LIST)" />
      <ParameterBinding Name="NoAnnouncementsHowTo" Location="Resource(wss,noXinviewofY_DEFAULT)" />
    </ParameterBindings>
  </View>
</Views>

フィーチャーを展開、アクティブ化、およびテストするには

  1. F5 キーを押してソリューションを展開し、フィーチャーをアクティブ化します。

  2. [サイトの操作] メニューで [サイトの設定] を選択します。

  3. [ギャラリー] で、[サイト列] をクリックします。プライマリ ルックアップ列がサイト列コレクションにあることを確認します。

  4. プライマリ ルックアップ列の名前をクリックします。[サイト内の列の変更] ページの [列を追加して、これらの各追加フィールドを表示] で、セカンダリ ルックアップ列の名前がオンになっていることを確認します。

  5. [サイトの設定] ページに戻ります。[ギャラリー] で、[サイト コンテンツ タイプ] をクリックします。

  6. コンテンツ タイプの名前をクリックします。[サイト コンテンツ タイプの情報] ページの [] で、プライマリ ルックアップ列が表示されていることを確認します。

  7. 左側のナビゲーション ウィンドウで、リストの名前をクリックします。

  8. リボンで [リスト] をクリックし、[リストの設定] をクリックします。

  9. [リストの設定] ページの [] で、プライマリ ルックアップ列とセカンダリ ルックアップ列が表示されていることを確認します。

  10. リスト ビューに戻ります。新しい項目をリストに追加してみます (場合によっては、最初にターゲット リストに項目を追加する必要があります)。

  11. 操作が完了したら、ブラウザーを閉じてデバッグを停止します。

    Visual Studio によってフィーチャーが非アクティブ化され、ソリューションが取り消されます。

次の手順

完全なフィーチャーは、非アクティブ化された時点で、作成したオブジェクトを削除します。Visual Studio は、繰り返し処理の多い開発の荒削りな部分を洗練させる目的で、できるだけこの処理を行おうとしますが、本番環境では、フィーチャーは、自身の後にクリーンアップを行うようになっています。これを行うには、コードをいくつか記述する必要があります。

クリーンアップ コードを配置する場所として適切なのは、SPFeatureReceiver クラスのサブクラスの FeatureDeactivating メソッドです。ここでの手順は、内部ポリシーによってある程度異なります。たとえば、重要なデータが含まれているリストは、ほとんどの場合、削除したくないと思います。この場合は、ユーザーがデータを回復できるように、そのデータを格納する手段を提供する必要があります。このような場合の考慮事項は別にして、FeatureDeactivating メソッドのコードを記述するときは、次の一般的なガイドラインに留意してください。

  • リスト コンテンツ タイプを削除してから、そのリスト コンテンツ タイプの派生元であるサイト コンテンツ タイプを削除します。

    静的メソッド SPContentTypeUsage.GetUsages を呼び出して、コンテンツ タイプが使用される場所に関する情報を取得できます。例については、SPContentTypeCollection クラスの Delete メソッドを参照してください。

  • サイト コンテンツ タイプを削除してから、そのサイト コンテンツ タイプが参照するサイト列を削除します。

  • セカンダリ ルックアップ列をすべて削除してから、そのセカンダリ ルックアップ列が依存するプライマリ ルックアップ列を削除します。

    例については、次の「ルックアップ列を既存のリストに追加する」の最後に記載されている、FeatureDeactivating メソッドの実装に関する説明を参照してください。

  • 必要に応じて管理者がトラブルシューティングできるように、例外とエラーをログに記録します。

ルックアップ列を既存のリストに追加する

ルックアップ列を既存のリストに追加するには、SharePoint Foundation オブジェクト モデルを使用するサーバー コードを記述します。これを行う最も良い方法は、フィーチャーを作成し、そのフィーチャーのイベント レシーバーにコードを記述することです。フィーチャーがアクティブ化されると、コードによってルックアップ列が作成されます。

注意

次の手順は、ルックアップ列のターゲットであるリストが、ルックアップ列を含むリストと同じ Web サイトに存在していることを前提としています。Web 間でルックアップすることができます。詳細については、LookupWebId プロパティを参照してください。

複数列ルックアップを既存のリストに追加するには

  1. Visual Studio 2010 で、SharePoint 2010 の [空の SharePoint プロジェクト] テンプレートを使用して、新しいプロジェクトを作成します。

  2. SharePoint カスタマイズ ウィザードで [サンドボックス ソリューションとして配置する] を選択し、[完了] をクリックします。

  3. ソリューション エクスプローラーで [Features] フォルダーを右クリックし、[フィーチャーの追加] をクリックします。

    フィーチャー デザイナーが開きます。ここで、タイトルと説明を編集し、フィーチャーの範囲を選択することができます。このアプリケーションに適したフィーチャーの範囲は Web または Site のどちらかです。詳細については、「要素の範囲」を参照してください。

  4. フィーチャー名 (既定では Feature1) を右クリックし、[イベント レシーバーの追加] を選択します。

    SPFeatureReceiver クラスのサブクラスが作成されます。

  5. FeatureActivated メソッドのコメントを解除します。

  6. FeatureActivated メソッドで、コードを記述して、現在の Web サイト (フィーチャーの範囲が Web の場合) またはサイト コレクションのルート Web サイト (範囲が Site の場合) を取得します。

    これを行うには、メソッドに properties パラメーターとして渡された SPFeatureReceiverProperties オブジェクトの Feature プロパティにアクセスします。Feature プロパティは SPFeature オブジェクトを返します。このオブジェクトの Parent プロパティは、Object 型としてボックス化された SPWeb オブジェクト (フィーチャーの範囲が Web の場合)、またはボックス化された SPSite オブジェクト (範囲が Site の場合) を返します。

    次のコード例は、この技法を示しています。

    SPWeb web = properties.Feature.Parent as SPWeb;
    if (web == null)
    {
        SPSite site = properties.Feature.Parent as SPSite;
        if (site != null)
            web = site.RootWeb;
    }
    
    Dim web As SPWeb = TryCast(properties.Feature.Parent, SPWeb)
    If web Is Nothing Then
        Dim site As SPSite = TryCast(properties.Feature.Parent, SPSite)
        If site IsNot Nothing Then
            web = site.RootWeb
        End If
    End
    
  7. 2 つの SPList オブジェクトをインスタンス化します。1 つはルックアップ列を受け取るリスト用で、もう 1 つはルックアップ列のターゲット リスト用です。

    たとえば、次のコード例は、Contoso Orders リストと Contoso Customers リストを表すオブジェクトを作成します。

    SPList customers = web.Lists.TryGetList("Contoso Customers");
    SPList orders = web.Lists.TryGetList("Contoso Orders");
    
    Dim customers As SPList = web.Lists.TryGetList("Contoso Customers")
    Dim orders As SPList = web.Lists.TryGetList("Contoso Orders")
    
  8. SPField オブジェクトをインスタンス化し、ルックアップ列のターゲットとなる列を表します。

    たとえば、次のコードはオブジェクトをインスタンス化し、Contoso Orders リストのルックアップ列のターゲットとなる Contoso Customers リストの 4 つの列を表します。

    SPField custID, custLName, custFName, custPhone;
    try
    {
        custID = customers.Fields.GetField("ID");
        custFName = customers.Fields.GetField("First Name");
        custLName = customers.Fields.GetField("Last Name");
        custPhone = customers.Fields.GetField("Contact Phone");
    }
    catch (ArgumentException ex)
    {
    
        // One of the fields was not found on the Customers list.
        System.Diagnostics.Trace.WriteLine(logEntry + ex.Message);
        return;
    }
    
    Dim custID, custLName, custFName, custPhone As SPField
    Try
        custID = customers.Fields.GetField("ID")
        custFName = customers.Fields.GetField("First Name")
        custLName = customers.Fields.GetField("Last Name")
        custPhone = customers.Fields.GetField("Contact Phone")
    Catch ex As ArgumentException
    
        ' One of the fields was not found on the Customers list.
        System.Diagnostics.Trace.WriteLine(logEntry + ex.Message)
        Return
    End Try
    
  9. ルックアップ列を受け取るリストの Fields プロパティによって返される SPFieldCollection オブジェクトの AddLookup メソッドを呼び出して、プライマリ ルックアップ列を作成します。

    AddLookup メソッドには 3 つのパラメーターがあります。

    • displayName - ルックアップ列の表示名を含む文字列。

    • lookupListId - ターゲット リストの ID である GUID。

    • bRequired --- ユーザーが New フォームおよび Edit フォームのルックアップ列の値を選択する必要があるかどうかを示す Boolean 値。

    メソッドは、ルックアップ列の内部名が含まれる文字列を返します。新しい列を表すオブジェクトを取得するには、内部名を GetFieldByInternalName メソッドに渡します。

    たとえば、次のコードは、Customer ID の表示名が含まれる Contoso Orders リストにルックアップ列を作成し、Constoso Customers リストをターゲットにします。

    string strPrimary = orders.Fields.AddLookup("Customer ID", customers.ID, true);
    
    Dim strPrimary As String = orders.Fields.AddLookup("Customer ID", customers.ID, True)
    
  10. ターゲット リストの列を参照するように、プライマリ ルックアップ列の LookupField プロパティを設定します。

    新しいルックアップ列を表す SPField オブジェクトを取得するには、AddLookup メソッドによって引数として返された内部名を GetFieldByInternalName(String) に渡します。次に、SPField オブジェクトを SPFieldLookup 型としてキャストし、LookupField プロパティにアクセスします。このプロパティはターゲット フィールドの内部名が含まれる文字列を受け入れます。

    次のコードは、前の手順の例で作成された列の LookupField プロパティを設定します。

    SPFieldLookup primary = orders.Fields.GetFieldByInternalName(strPrimary) as SPFieldLookup;
    primary.LookupField = custID.InternalName;
    primary.Update();
    
    Dim primary As SPFieldLookup = TryCast(orders.Fields.GetFieldByInternalName(strPrimary), SPFieldLookup)
    primary.LookupField = custID.InternalName
    primary.Update()
    
  11. ルックアップ列が挿入されるリストのフィールド コレクションの AddDependentLookup メソッドを呼び出して、セカンダリ ルックアップ列を作成します。

    AddDependentLookup メソッドには 2 つのパラメーターがあります。

    • displayName - ルックアップ列の表示名を含む文字列。

    • primaryLookupFieldId - プライマリ ルックアップ列の ID である GUID。

    AddLookup と同様に、AddDependentLookup メソッドは、新しい列の内部名が含まれる文字列を返します。

    次のコード行は、前の例で作成されたプライマリ ルックアップ列に依存する Last Name 列を作成します。

    string strLName = orders.Fields.AddDependentLookup("Last Name", primary.Id);
    
    Dim strLName As String = orders.Fields.AddDependentLookup("Last Name", primary.Id)
    
  12. 手順 10. と同じ手順に従って、新しいセカンダリ ルックアップ列の LookupField プロパティを設定します。

  13. 追加するセカンダリ ルックアップ列ごとに、手順 10. ~ 11. を繰り返します。

  14. (オプション) 各ビューの ViewFields プロパティによって返された SPViewFieldCollection オブジェクトの Add メソッドを呼び出して、1 つ以上のルックアップ列をリスト ビューに追加します。

次の例は、Contoso Orders リストのルックアップ列を作成および削除する SPFeatureReceiver クラスのサブクラスの完全なコードを示しています。FeatureActivated メソッドのコードは、まず、Contoso Customers リストの ID 列の値を参照する Customer ID という名前のプライマリルックアップ列を作成します。次に、First Name、Last Name、および Phone のセカンダリ ルックアップ列を作成し、セカンダリ列を Contoso Orders リストの既定のビューに追加します。

この例には FeatureDeactivating メソッドのコードも含まれており、これにより FeatureActivated で作成されたすべてのルックアップ列が削除されます。セカンダリ ルックアップ列をすべて削除してから、そのセカンダリ ルックアップ列が依存するプライマリ ルックアップ列を削除する必要があることに注意してください。

using System;
using System.Runtime.InteropServices;
using Microsoft.SharePoint;

namespace Contoso.Orders.Features.CustomerLookups
{
    [Guid("49e72c4b-cfcb-4665-9c2a-fdadf0a3b018")]
    public class CustomerLookupsEventReceiver : SPFeatureReceiver
    {

        // Define static field names.
        const string STATIC_CUST_ID = "CustID";
        const string STATIC_CUST_FNAME = "CustFName";
        const string STATIC_CUST_LNAME = "CustLName";
        const string STATIC_CUST_PHONE = "CustPhone";

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            string logEntry = properties.Definition.DisplayName + " activation error: ";

            // Get an object representing either the current website (if the scope is Web)
            // or the root website (if the scope is Site).
            SPWeb web = properties.Feature.Parent as SPWeb;
            if (web == null)
            {
                SPSite site = properties.Feature.Parent as SPSite;
                if (site != null)
                    web = site.RootWeb;
            }
            if (web == null)
            {
                System.Diagnostics.Trace.WriteLine(logEntry + "Invalid scope");
                return;
            }

            // Get objects for the two lists.
            SPList customers = web.Lists.TryGetList("Contoso Customers");
            SPList orders = web.Lists.TryGetList("Contoso Orders");
            if (customers == null || orders == null)
            {
                System.Diagnostics.Trace.WriteLine(logEntry + "List not found");
                return;
            }

            // Get the fields from the Customers list that will be seen on the Orders list.
            SPField custID, custLName, custFName, custPhone;
            try
            {
                custID = customers.Fields.GetField("ID");
                custFName = customers.Fields.GetField("First Name");
                custLName = customers.Fields.GetField("Last Name");
                custPhone = customers.Fields.GetField("Contact Phone");
            }
            catch (ArgumentException ex)
            {
                // One of the fields was not found on the Customers list.
                System.Diagnostics.Trace.WriteLine(logEntry + ex.Message);
                return;
            }

            /* 
            * Create a multi-column lookup on the Orders list. 
            */

            // Create the primary column: Customer ID.
            string strPrimary = orders.Fields.AddLookup("Customer ID", customers.ID, true);

            SPFieldLookup primary = orders.Fields.GetFieldByInternalName(strPrimary) as SPFieldLookup;
            primary.LookupField = custID.InternalName;
            primary.StaticName = STATIC_CUST_ID;
            primary.Update();

            // Create a secondary column: First Name.
            string strFName = orders.Fields.AddDependentLookup("First Name", primary.Id);

            SPFieldLookup ordersFName = orders.Fields.GetFieldByInternalName(strFName) as SPFieldLookup;
            ordersFName.LookupField = custFName.InternalName;
            ordersFName.StaticName = STATIC_CUST_FNAME;
            ordersFName.Update();

            // Create a secondary column: Last Name.
            string strLName = orders.Fields.AddDependentLookup("Last Name", primary.Id);

            SPFieldLookup ordersLName = orders.Fields.GetFieldByInternalName(strLName) as SPFieldLookup;
            ordersLName.LookupField = custLName.InternalName;
            ordersLName.StaticName = STATIC_CUST_LNAME;
            ordersLName.Update();

            // Create a secondary column: Phone.
            string strPhone = orders.Fields.AddDependentLookup("Phone", primary.Id);

            SPFieldLookup ordersPhone = orders.Fields.GetFieldByInternalName(strPhone) as SPFieldLookup;
            ordersPhone.LookupField = custPhone.InternalName;
            ordersPhone.StaticName = STATIC_CUST_PHONE;
            ordersPhone.Update();

            // Add columns to the default view.
            AddToDefaultView(orders, strFName);
            AddToDefaultView(orders, strLName);
            AddToDefaultView(orders, strPhone);
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            string logEntry = properties.Definition.DisplayName + " deactivation error: ";

            // Get an object representing either the current website (if the scope is Web)
            // or the root website (if the scope is Site).
            SPWeb web = properties.Feature.Parent as SPWeb;
            if (web == null)
            {
                SPSite site = properties.Feature.Parent as SPSite;
                if (site != null)
                    web = site.RootWeb;
            }
            if (web == null)
            {
                System.Diagnostics.Trace.WriteLine(logEntry + "Invalid scope");
                return;
            }

            // Get the Orders list.
            SPList orders = web.Lists.TryGetList("Contoso Orders");
            if (orders == null)
            {
                System.Diagnostics.Trace.WriteLine(logEntry + "List not found");
                return;
            }

            // Delete the lookup fields.
            // Note that you must delete dependent lookup fields
            // before deleting the primary lookup field.
            SPFieldLookup primaryLookup = orders.Fields.TryGetFieldByStaticName(STATIC_CUST_ID) as SPFieldLookup;
            if (primaryLookup != null && !primaryLookup.IsDependentLookup)
            {
                string[] dependentLookupNames = primaryLookup.GetDependentLookupInternalNames().ToArray();
                if (dependentLookupNames.Length != 0)
                {
                    foreach (string dependent in dependentLookupNames)
                    {
                        orders.Fields.Delete(dependent);
                    }
                }
                primaryLookup.Delete();
            }

        }

        public void AddToDefaultView(SPList list, string fieldName)
        {
            if (list != null && list.Fields.ContainsField(fieldName) && !list.DefaultView.ViewFields.Exists(fieldName))
            {
                SPView defaultView = list.DefaultView;
                defaultView.ViewFields.Add(fieldName);
                defaultView.Update();
            }
        }
    }
}
Option Explicit On
Option Strict On

Imports System
Imports System.Runtime.InteropServices
Imports Microsoft.SharePoint


<GuidAttribute("c17f29fb-670e-41ba-af43-8a1e97c1cae5")> _
Public Class CustomerLookupsEventReceiver 
    Inherits SPFeatureReceiver

    ' Define static field names.
    Const STATIC_CUST_ID As String = "CustID"
    Const STATIC_CUST_FNAME As String = "CustFName"
    Const STATIC_CUST_LNAME As String = "CustLName"
    Const STATIC_CUST_PHONE As String = "CustPhone"

 
    Public Overrides Sub FeatureActivated(ByVal properties As SPFeatureReceiverProperties)
        Dim logEntry As String = properties.Definition.DisplayName + " activation error: "

        ' Get an object representing either the current website (if the scope is Web)
        ' or the root website (if the scope is Site).
        Dim web As SPWeb = TryCast(properties.Feature.Parent, SPWeb)
        If web Is Nothing Then
            Dim site As SPSite = TryCast(properties.Feature.Parent, SPSite)
            If site IsNot Nothing Then
                web = site.RootWeb
            End If
        End If
        If web Is Nothing Then
            System.Diagnostics.Trace.WriteLine(logEntry + "Invalid scope")
            Return
        End If

        ' Get objects for the two lists.
        Dim customers As SPList = web.Lists.TryGetList("Contoso Customers")
        Dim orders As SPList = web.Lists.TryGetList("Contoso Orders")
        If customers Is Nothing OrElse orders Is Nothing Then
            System.Diagnostics.Trace.WriteLine(logEntry + "List not found")
            Return
        End If

        ' Get the fields from the Customers list that will be seen on the Orders list.
        Dim custID, custLName, custFName, custPhone As SPField
        Try
            custID = customers.Fields.GetField("ID")
            custFName = customers.Fields.GetField("First Name")
            custLName = customers.Fields.GetField("Last Name")
            custPhone = customers.Fields.GetField("Contact Phone")
        Catch ex As ArgumentException

            ' One of the fields was not found on the Customers list.
            System.Diagnostics.Trace.WriteLine(logEntry + ex.Message)
            Return
        End Try

        ' 
        '  Create a multi-column lookup on the Orders list. 
        '            

        ' Create the primary column: Customer ID.
        Dim strPrimary As String = orders.Fields.AddLookup("Customer ID", customers.ID, True)

        Dim primary As SPFieldLookup = TryCast(orders.Fields.GetFieldByInternalName(strPrimary), SPFieldLookup)
        primary.LookupField = custID.InternalName
        primary.StaticName = STATIC_CUST_ID
        primary.Update()

        ' Create a secondary column: First Name.
        Dim strFName As String = orders.Fields.AddDependentLookup("First Name", primary.Id)

        Dim ordersFName As SPFieldLookup = TryCast(orders.Fields.GetFieldByInternalName(strFName), SPFieldLookup)
        ordersFName.LookupField = custFName.InternalName
        ordersFName.StaticName = STATIC_CUST_FNAME
        ordersFName.Update()

        ' Create a secondary column: Last Name.
        Dim strLName As String = orders.Fields.AddDependentLookup("Last Name", primary.Id)

        Dim ordersLName As SPFieldLookup = TryCast(orders.Fields.GetFieldByInternalName(strLName), SPFieldLookup)
        ordersLName.LookupField = custLName.InternalName
        ordersLName.StaticName = STATIC_CUST_LNAME
        ordersLName.Update()

        ' Create a secondary column: Phone.
        Dim strPhone As String = orders.Fields.AddDependentLookup("Phone", primary.Id)

        Dim ordersPhone As SPFieldLookup = TryCast(orders.Fields.GetFieldByInternalName(strPhone), SPFieldLookup)
        ordersPhone.LookupField = custPhone.InternalName
        ordersPhone.StaticName = STATIC_CUST_PHONE
        ordersPhone.Update()

        ' Add columns to the default view.
        AddToDefaultView(orders, strFName)
        AddToDefaultView(orders, strLName)
        AddToDefaultView(orders, strPhone)
    End Sub

    Public Overrides Sub FeatureDeactivating(ByVal properties As SPFeatureReceiverProperties)

        Dim logEntry As String = properties.Definition.DisplayName + " deactivation error: "

        ' Get an object representing either the current website (if the scope is Web)
        ' or the root website (if the scope is Site).
        Dim web As SPWeb = TryCast(properties.Feature.Parent, SPWeb)
        If web Is Nothing Then
            Dim site As SPSite = TryCast(properties.Feature.Parent, SPSite)
            If site IsNot Nothing Then
                web = site.RootWeb
            End If
        End If
        If web Is Nothing Then
            System.Diagnostics.Trace.WriteLine(logEntry + "Invalid scope")
            Return
        End If

        ' Get the Orders list.
        Dim orders As SPList = web.Lists.TryGetList("Contoso Orders")
        If orders Is Nothing Then
            System.Diagnostics.Trace.WriteLine(logEntry + "List not found")
            Return
        End If

        ' Delete the lookup fields.
        ' Note that you must delete dependent lookup fields
        ' before deleting the primary lookup field.
        Dim primaryLookup As SPFieldLookup = TryCast(orders.Fields.TryGetFieldByStaticName(STATIC_CUST_ID), SPFieldLookup)
        If primaryLookup IsNot Nothing AndAlso Not primaryLookup.IsDependentLookup Then
            Dim dependentLookupNames As String() = primaryLookup.GetDependentLookupInternalNames().ToArray()
            If dependentLookupNames.Length > 0 Then
                For Each dependent As String In dependentLookupNames
                    orders.Fields.Delete(dependent)
                Next
            End If
            primaryLookup.Delete()
        End If

    End Sub

    Public Sub AddToDefaultView(ByVal list As SPList, ByVal fieldName As String)
        If list IsNot Nothing AndAlso list.Fields.ContainsField(fieldName) AndAlso Not list.DefaultView.ViewFields.Exists(fieldName) Then
            Dim defaultView As SPView = list.DefaultView
            defaultView.ViewFields.Add(fieldName)
            defaultView.Update()
        End If
    End Sub

End Class

関連項目

参照

Field 要素 (フィールド)

SPFieldLookup

AddLookup(String, Guid, Boolean)

AddDependentLookup(String, Guid)

概念

ルックアップとリストのリレーションシップ