如何:创建多列查阅

上次修改时间: 2010年12月1日

适用范围: SharePoint Foundation 2010

在 Microsoft SharePoint Foundation 中,查阅 列配置为显示另一列表中的列值。用户创建新项目时,他们不会为查阅列键入值,而是从其他列表的列值下拉列表中选择一个值。在 SharePoint Foundation 2010 中,可以创建多列查阅,其中包含一个 查阅列和一个或多个辅助 查阅列,前者用于选择目标列表中的项目,后者显示同一列表项中其他列的值。

查阅列的目标可以是下列字段类型之一: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。第二个选项是一个相对于 Web 的 URL,它仅在目标列表尚不存在的情况下有效。在这种情况下,必须在创建查阅列的功能中创建目标列表。

如果目标列表已存在,则可以通过编写简单的控制台应用程序来获取其 ID,该应用程序获取对表示该列表的 SPList 对象的引用并将 ID 属性的值输出到控制台。所需的值由 System.Guid 类的 ToString("B") 方法返回。

using (SPSite site = new SPSite("https://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。打开网站,在导航窗格中选择"列表和库",右键单击列表的名称,并选择"列表设置"。在"列表信息"下查找"列表 ID"。复制整个 GUID,包括大括号。

此外,还需要每个查阅字段将指向的每个目标列表字段的内部名称。如果您正在查看字段定义,则内部名称为 Field 元素的 Name 属性的值;如果要通过编写代码收集信息,则为 SPField 对象的 InternalName 属性返回的值。

提示提示

可以通过浏览 SPBuiltInFieldId 类的文档来查找内置列的内部名称。该类中每个字段的名称均是某一内置列的内部名称。例如,"创建者"字段的内部名称为 Created_x0020_By

用于在新列表中创建多列查阅的常规过程涉及下列几项任务:

  1. 将查阅列定义为网站栏。

  2. 定义使用查阅列的内容类型。

  3. 基于新内容类型定义列表和列表实例。

  4. 部署、激活和测试功能。

将查阅列定义为网站栏

  1. 在 Visual Studio 2010 中,使用"空白 SharePoint 项目"模板创建新 SharePoint 2010 项目。

  2. 在"SharePoint 自定义向导"中,选择"部署为沙盒解决方案",然后单击"完成"。

  3. 在"解决方案资源管理器"中,右键单击"功能"文件夹,然后选择"添加功能"。

    将显示功能设计器。可以编辑标题和说明,并且可以选择功能的范围。WebSite 是适合此应用程序的范围。有关详细信息,请参阅元素的作用域

  4. (可选)为查阅创建目标列表。

    若要根据自定义列表定义创建目标列表,请按照如何:创建自定义列表定义中所述的过程执行操作。若要根据现有列表定义创建目标列表,请执行以下步骤:

    1. 在"解决方案资源管理器"中,选择项目,然后在"项目"菜单上,选择"添加新项"。

    2. 在"添加新项"对话框中,选择"列表实例"模板并为该列表键入名称。单击"添加"。

    3. 按照"SharePoint 自定义向导"中的提示操作。

      该向导要求您选择列表模板,并指定列表的 URL。

  5. 为主查阅列创建字段定义

    1. 在"解决方案资源管理器"中,单击项目,然后在"项目"菜单上,选择"添加新项"。

    2. 在"添加新项"对话框中,选择"空元素"模板,为元素键入名称(例如,"SiteColumns"),然后单击"添加"。

      Visual Studio 使用您键入的名称作为它添加到项目中的文件夹的名称。在该文件夹中,Visual Studio 将创建名为 Elements.xml 的文件。

    3. 在 Elements.xml 的 Elements 元素中,插入以下 XML:

      <!-- Primary lookup column -->
      <Field Type="Lookup" Name="" ID="" List="" ShowField="" DisplayName="" Required="" Group="" />
      
    4. 为 Name 属性键入值。

      这是字段的内部名称。在将创建此字段的网站的 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 的 Elements 元素中,插入以下 XML:

      <!-- Secondary lookup column -->
      <Field Type="Lookup" FieldRef="" Name="" ID="" List="" ShowField="" DisplayName="" Required="" Group="" ReadOnly="TRUE" />
      
    2. 为 FieldRef 属性指定值。

      此属性引用主查阅列的字段定义。使用主查阅的 ID 属性,但省略大括号

    3. 为其余属性指定值,如步骤 5 中所示。

  7. 根据需要多次重复步骤 6,以便为功能中的每个其余辅助查阅列创建字段定义。

此时,您的字段定义应类似于下面的示例,它定义了对 Contoso Customers 列表的多列查阅。

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="https://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="https://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 使用您键入的名称作为要添加到项目中的文件夹的名称。该文件夹包含以下文件:一个名为 Elements.xml 的文件,其中包含 ListTemplate 元素;一个名为 Schema.xml 的文件,其中包含 List 元素;以及一个名为 ListInstance1 的文件夹,其中包含具有 ListInstance 元素的另一 Elements.xml 文件。

  4. 打开 Schema.xml 文件。

    请注意,ContentTypes 元素包含内容类型定义的副本,并且 Fields 元素包含查阅列的字段定义的副本。

    向下滚动到 Views 元素。请注意,定义了两个视图,但两个视图都不包含引用查阅列的 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 的查阅。有关详细信息,请参阅 LookupWebId 属性。

向现有列表中添加多列查阅

  1. 在 Visual Studio 2010 中,使用"空白 SharePoint 项目"模板创建新 SharePoint 2010 项目。

  2. 在"SharePoint 自定义向导"中,选择"部署为沙盒解决方案"。单击"完成"。

  3. 在"解决方案资源管理器"中,右键单击"功能"文件夹,然后选择"添加功能"。

    将显示功能设计器。可以编辑标题和说明,并且可以选择功能的范围。WebSite 是适合此应用程序的范围。有关详细信息,请参阅元素的作用域

  4. 右键单击功能名称(默认为 Feature1),然后选择"添加事件接收器"。

    Visual Studio 将创建 SPFeatureReceiver 类的一个子类。

  5. 取消注释 FeatureActivated 方法。

  6. 在 FeatureActivated 方法中,编写代码以获取当前网站(如果功能范围为 Web)或网站集的根网站(如果范围为 Site)。

    为此,可以访问作为 properties 参数传递给该方法的 SPFeatureReceiverProperties 对象的 Feature 属性。Feature 属性返回 SPFeature 对象。如果功能的范围为 Web,则此对象的 Parent 属性返回封装为 Object 类型的 SPWeb 对象;如果范围为 Site,则返回封装的 SPSite 对象。

    下面的代码示例演示了此技术。

    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. 实例化两个 SPList 对象,一个用于将接收查阅列的列表,另一个用于作为查阅列目标的列表。

    例如,以下代码示例创建表示 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 Customers 列表中四个列的对象,这些列将作为 Contoso Orders 列表中查阅列的目标。

    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. 通过调用 SPFieldCollection 对象的 AddLookup 方法来创建主查阅列,该对象由将接收查阅列的列表的 Fields 属性返回。

    AddLookup 方法有三个参数:

    • displayName - 包含查阅列的显示名称的字符串。

    • lookupListId - 作为目标列表 ID 的 GUID。

    • bRequired - 一个 Boolean 值,指示用户是否必须在 New 和 Edit 表单上为查阅列选择值。

    该方法返回包含查阅列的内部名称的字符串。您可以将内部名称传递给 GetFieldByInternalName 方法,以检索表示新列的对象。

    例如,以下代码在 Contoso Orders 列表中创建查阅列,该查阅列的显示名称为 Customer ID,目标为 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 属性,使其指向目标列表中的某一列。

    可以将 AddLookup 方法返回的内部名称作为参数传递给 GetFieldByInternalName(String),以检索表示新主查阅列的 SPField 对象。然后在访问 LookupField 属性之前将 SPField 对象转换为 SPFieldLookup 类型。此属性接受包含目标字段内部名称的字符串。

    以下代码设置在示例的前一步骤中创建的列的 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 方法具有两个参数:

    • 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. (可选。)通过调用 SPViewFieldCollection 对象的 Add 方法来向列表视图中添加一个或多个查阅列,该对象由每个视图的 ViewFields 属性返回。

示例

下面的示例显示 SPFeatureReceiver 类的子类的完整代码,该代码用于在 Contoso Orders 列表中创建和删除查阅列。FeatureActivated 方法中的代码创建名为 Customer ID 的主查阅列,该列查找 Contoso Customers 列表中 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)

概念

查阅和列表关系