Поделиться через


Практическое руководство. Создание столбца подстановки с несколькими столбцами

Дата последнего изменения: 1 декабря 2010 г.

Применимо к: SharePoint Foundation 2010

В Microsoft SharePoint Foundation столбец подстановки — это столбец, который настроен на отображение значения, содержащегося в столбце другого списка. Когда пользователи создают новый элемент, им не требуется вводить значение для столбца подстановки; им нужно просто выбрать требуемое значение в раскрывающемся списке, который содержит значения из столбца другого списка. В SharePoint Foundation 2010 можно создать столбец подстановки с несколькими столбцами, в котором основной столбец подстановки используется для выбора элемента в целевом списке, а один или несколько дополнительных столбцов подстановки отображают значения из других столбцов в том же элементе списка.

Целевой столбец столбца подстановки может содержать поля следующих типов: Counter, DateTime, Number и Text. Дополнительные сведения об этих типах полей см. в описании перечисления SPFieldType. Кроме того, целевой столбец может содержать поле типа Calculated, если формат выходных данных является текстовым. Дополнительные сведения см. в разделе справки, посвященном свойству OutputType класса SPFieldCalculated. Тип поля Computed может быть целевым, если для поля включены подстановки. Дополнительные сведения см. в разделе справки, посвященном свойству EnableLookup класса SPFieldComputed.

Способ создания столбца подстановки с несколькими столбцами зависит от того, требуется ли определять столбцы для нового списка или добавлять столбцы в существующий список. В любом случае в контексте компонента будут создаваться столбцы. Дополнительные сведения о реализации компонента см. в статье Использование компонентов.

Создание столбцов подстановки в новом списке

При создании столбцов подстановки в списке, который также создается как часть компонента, самый простой способ определения столбцов и списка заключается в написании декларативного XML-кода. разработки SharePoint в Microsoft Visual Studio 2010 содержат несколько шаблонов, которые выполняют часть работы за разработчика. Шаблоны также создают пакет решения для компонента, автоматически развертывают пакет при нажатии клавиши F5 и отзывают решение при остановке отладки. Это существенно упрощает управление процессом последовательной разработки.

Основной и дополнительный столбцы подстановки можно определить в ходе определения нового списка (т. е. как часть схемы списка). Однако гораздо удобнее создать столбцы сайта, добавить их в тип контента сайта и использовать тип контента в качестве основы нового списка. Этот метод позволяет многократно использовать столбцы в других списках. Кроме того, такой подход позволяет поддерживать и обновлять определения столбца независимо от определения списка.

Прежде чем начать, необходимо получить дополнительные сведения о списке, который будет являться целевым списком столбцов подстановки. Во-первых, необходимо выяснить, как определить целевой список. Столбец подстановки, как и любой другой столбец, определяется с помощью элемента Field в XML-файле. Целевой список для столбца подстановки определяется значением атрибута List элемента Field. Значением атрибута может быть либо идентификатор списка (GUID) или URL-адрес. URL-адрес используется в случае, если целевой список еще не создан. В этом случае необходимо создать целевой список в том же компоненте, который создает столбец подстановки.

Если целевой список уже существует, для получения его идентификатора можно использовать простое консольное приложение, которое возвращает ссылку на объект SPList, представляющий список, и выводит значение свойства ID на консоль. Требуемое значение возвращается методом ToString("B") класса System.Guid.

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. Откройте веб-сайт, в области навигации выберите Списки и библиотеки, щелкните правой кнопкой мыши имя списка и выберите пункт Параметры списка. Найдите ИД списка в разделе Сведения о списке. Скопируйте GUID вместе со скобками.

Кроме того, потребуется внутреннее имя каждого поля в целевом списке, на которое будет указывать одно из полей подстановки. Внутреннее имя — это значение атрибута Name элемента Field, если выполняется поиск в определении поля, или значение, возвращаемое свойством InternalName объекта SPField, если выполняется сбор данных посредством написания кода.

СоветСовет

Внутренние имена встроенных столбцов можно найти путем просмотра документации по классу SPBuiltInFieldId. Имя каждого поля в классе — это внутреннее имя встроенного столбца. Например, внутреннее имя поля СозданCreated_x0020_By.

Процедура создания столбца подстановки с несколькими столбцами в новом списке состоит из следующих задач:

  1. Определение столбцов подстановки в качестве столбцов сайта.

  2. Определение типа контента, используемого столбцами подстановки.

  3. Определение списка и экземпляра списка на основании нового типа контента.

  4. Развертывание, активация и проверка компонента.

Определение столбцов подстановки в качестве столбцов сайта

  1. Создайте в Visual Studio 2010 проект на основе шаблона Пустой проект SharePoint для SharePoint 2010.

  2. В окне Мастер настройки SharePoint выберите пункт Развернуть как изолированное решение и нажмите кнопку Готово.

  3. В окне Обозреватель решений щелкните правой кнопкой мыши папку Компоненты и выберите команду Добавить компонент.

    Откроется конструктор компонентов, в котором можно изменить название и описание компонента, а также выбрать для него область. Для данного приложения подходит область Веб или Сайт. Дополнительные сведения см. в статье Область элемента.

  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. Укажите значение атрибута ID путем вставки нового GUID (включая скобки) между кавычками.

    7. Укажите значение атрибута List.

      Атрибут List определяет целевой список столбца подстановки. Если целевой список уже существует, значением является идентификатор списка, т. е. GUID (включая скобки).

      Если целевой список еще не создан, в качестве значения атрибута List можно использовать URL-адрес, указанный относительно веб-сайта (например, Lists/Contoso Customers). Однако необходимо создать список как часть того же компонента, который создает столбец подстановки (см. шаг 4). Используйте значение атрибута Url элемента ListInstance, который создает целевой список.

    8. Укажите значение атрибута ShowField.

      Значение атрибута ShowField — это внутреннее имя целевого поля в списке, определяемом атрибутом List.

    9. Укажите значение атрибута DisplayName.

      Это имя, которое отображается для столбца в представлениях списка и формах. Максимальная длина — 255 символов. Значение может быть ссылкой на локализованный ресурс в формате $Resources:String. Дополнительные сведения см. в статье, посвященной локализации решений SharePoint.

    10. Присвойте атрибуту Required значение true или false.

      Укажите значение true, если пользователи, заполняющие форму New или Edit для элемента списка должны выбирать значение поля. Укажите значение 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 (Клиенты Contoso).

<?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 присваивает атрибуту Inherits элемента ContentType значение 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, содержащая файл Elements.xml с элементом ListInstance.

  4. Откройте файл Schema.xml.

    Обратите внимание, что элемент ContentTypes содержит копию определения типа контента, а элемент Fields содержит копию определений полей для столбцов подстановки.

    Выполните прокрутку до элемента Views. Обратите внимание, что определены два представления, но ни одно из них не содержит элементы FieldRef, ссылающиеся на столбцы подстановки.

  5. Скопируйте элементы FieldRef для любого столбца, который необходимо отобразить в представлении списка, и вставьте их в элемент ViewFields описания представления.

    Атрибуты ID и Name являются обязательными для элементов FieldRef, находящихся внутри элемента ViewFields.

Элемент Views в файле Schema.xml должен быть похож на следующий пример.

<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 пытается сделать все возможное, чтобы нивелировать погрешности процесса последовательной разработки, однако в рабочей среде предполагается, что компонент удаляет созданные им объекты после отключения. Для этого потребуется написать дополнительный код.

Правильнее всего разместить код, выполняющий очистку, в методе FeatureDeactivating подкласса класса SPFeatureReceiver. Дальнейшие действия зависят от внутренней политики. Например, возможно вам не потребуется удалять списки, если в них содержатся ценные данные. В этом случае потребуется предоставить способ сохранения данных, чтобы пользователи смогли восстановить данные при необходимости. Помимо этого необходимо помнить о следующих общих принципах, имеющих место при написании кода для метода FeatureDeactivating:

  • Удаляйте типы контента списка перед удалением типа контента сайта, от которого наследуются типы.

    Чтобы получить сведения о том, где используется тип контента, можно вызвать статический метод SPContentTypeUsage.GetUsages. В качестве примера рассмотрите реализацию метода Delete в классе SPContentTypeCollection.

  • Удаляйте типы контента сайта перед удалением столбцов сайта, на которые они ссылаются.

  • Удаляйте все дополнительные столбцы подстановки перед удалением основного столбца подстановки, от которого они зависят.

    В качестве примера рассмотрите реализацию метода FeatureDeactivating в конце следующего раздела "Добавление столбцов подстановки в существующий список".

  • Регистрируйте в журнале исключения и сбои, чтобы администратор смог быстро устранить неполадку.

Добавление столбцов подстановки в существующий список

Для добавления столбцов подстановки в существующий список можно написать серверный код, использующий объектную модель SharePoint Foundation. Для этого необходимо создать компонент и написать код в приемнике событий компонента. Код создаст столбцы подстановки при активации компонента.

ПримечаниеПримечание

В следующей процедуре предполагается, что целевой список столбцов подстановки существует на том же веб-сайте, что и список, содержащий столбцы подстановки. Возможны межсайтовые подстановки. Дополнительные сведения см. в разделе справки, посвященном свойству LookupWebId.

Добавление столбцов подстановки с несколькими столбцами в существующий список

  1. Создайте в Visual Studio 2010 проект на основе шаблона Пустой проект SharePoint для SharePoint 2010.

  2. В окне Мастер настройки SharePoint выберите пункт Развернуть как изолированное решение и нажмите кнопку Готово.

  3. В окне Обозреватель решений щелкните правой кнопкой мыши папку Компоненты и выберите команду Добавить компонент.

    Откроется конструктор компонентов, в котором можно изменить название и описание компонента, а также выбрать для него область. Для данного приложения подходит область Веб или Сайт. Дополнительные сведения см. в статье Область элемента.

  4. Щелкните правой кнопкой мыши имя компонента (по умолчанию Feature1) и выберите команду Добавить приемник событий.

    Visual Studio создаст подкласс класса SPFeatureReceiver.

  5. Удалите комментарии метода FeatureActivated.

  6. В метод FeatureActivated добавьте код, возвращающий либо текущий веб-сайт (для области Web) или корневой веб-сайт семейства веб-сайтов (для области Site).

    Для этого можно использовать свойство Feature объекта SPFeatureReceiverProperties, которое передается методу в качестве параметра properties. Свойство Feature возвращает объект SPFeature. Свойство Parent объекта возвращает объект SPWeb типа Object, если областью компонента является Веб, или как объект 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) и Contoso Customers (клиенты Contoso).

    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), который будет целевым списком столбцов подстановки в списке Contoso Orders (Заказы Contoso).

    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. Создайте основной столбец подстановки, вызвав метод AddLookup объекта SPFieldCollection, возвращаемого свойством Fields списка, который будет получать столбцы подстановки.

    Метод AddLookup содержит три параметра:

    • displayName — строка, содержащая отображаемое имя для столбца подстановки.

    • lookupListId — GUID, который является идентификатором целевого списка.

    • bRequired — логический (Boolean) параметр, указывающий, должны ли пользователи выбирать значение для столбца подстановки в формах New и Edit.

    Метод возвращает строку, содержащую внутреннее имя столбца подстановки. Можно загрузить объект, который представляет новый столбец путем передачи внутреннего имени методу GetFieldByInternalName.

    Например, следующий код создает столбец подстановки в списке Contoso Orders (Заказы Contoso), который содержит отображаемое имя Customer ID (ИД клиента), и указывает в качестве целевого списка список Constoso Customers (Клиенты Contoso).

    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 принимает два параметра:

    • displayName — строка, содержащая отображаемое имя для столбца подстановки.

    • primaryLookupFieldId — 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. Задайте свойство LookupField нового дополнительного столбца подстановки, как описано на шаге 10.

  13. Повторите шаги 10– 11 для каждого дополнительного столбца подстановки, который необходимо добавить.

  14. (Необязательный шаг). Добавьте один или несколько столбцов подстановки в представления списков путем вызова метода Add объекта SPViewFieldCollection, возвращаемого свойством ViewFields каждого из представлений.

Пример

В приведенном ниже примере продемонстрирован весь код для подкласса класса SPFeatureReceiver, который создает и удаляет столбцы подстановки в списке Contoso Orders (заказы Contoso). Код метода FeatureActivated создает основной столбец подстановки Customer ID (ИД клиента), который выполняет поиск значения в столбце идентификаторов в списке Contoso Customers (клиенты Contoso). Затем код создает дополнительные столбцы подстановки для столбцов First Name (имя), Last Name (фамилия) и Phone (телефон) и добавляет их в представление по умолчанию в списке Contoso Orders (заказы Contoso).

В примере также содержится код для метода 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 (Field)

SPFieldLookup

AddLookup(String, Guid, Boolean)

AddDependentLookup(String, Guid)

Концепции

Отношения между списками и подстановки