Link blog.vitalyzhukov.ru

Блог переехал вот сюда: Blog.VitalyZhukov.ru

23 янв. 2011 г.

SharePoint 2010. Создаем тип содержимого (ContentType)

Что делаем
Создадим 3 своих типа содержимого. Пускай это будет департамент (Department), сотрудник (Employee), VIP-сотрудник (VipEmployee). Также сделаем два списка: департаменты (Departments) и сотрудники (Employees). Департамент будет связан с сотрудниками связью один ко многим. Немного усложним и свяжем департамент с самим собой, чтобы получилась у нас орг. структура.



Делаем
В проект на Visual Studio 2010 добавляем новый элемент в проект, а именно ContentType. Студия нам предложит выбрать тип содержимого от которого будет унаследован наш тип - выбираем Item, везде кроме типа VipEmployee, его надо будет унаследовать от нашего же Employee. Итак делаем три раза (Department, Employee, VipEmployee). Я думая, все понятно и без картинок. 
У меня получилось примерно так:
Внутри наш тип содержимого сейчас выглядит вот так:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!-- Parent ContentType: ZhukPointContentType - Employee (ZhukPointContentType\Employee) (0x0100568056018ffd49a9ae1fd388c517ab64) -->
  <ContentType ID="0x0100568056018ffd49a9ae1fd388c517ab6400082bbb65070f425abd85c5e8b78bf1a1"
               Name="ZhukPointContentType - VipEmployee"
               Group="Custom Content Types"
               Description="My Content Type"
               Inherits="TRUE"
               Version="0">
    <FieldRefs>
    </FieldRefs>
  </ContentType>
</Elements>


Атрибут ID у элемента ContentType содержит ID родительского типа. Строится он по следующему правилу: берется ID родительского типа и справа наращиваем ID текущего типа, отделяя его двумя нулями.
<ID родительского типа>00<ID типа (Guid)>

Теперь вдохнем в наши пустышки смысл. Сначала добавим поля, для чего их надо просто обозначить, добавив записи в FieldRefs. Для сотрудника у меня получилось следующее:
<FieldRefs>
  <FieldRef ID="a160c2699bbc402b9a501673e0ce5588" Name="Name" DisplayName="Имя" />
  <FieldRef ID="e74fa9434d7d484d99f51bb210f4c1c1" Name="Surname" DisplayName="Фамилия" />
  <FieldRef ID="8b867c02b39b49598785a094fa067321" Name="Position" DisplayName="Должность" />
  <FieldRef ID="c6964dd5d3df44fe94c6b3908c756f80" Name="Department" DisplayName="Департамент" />
</FieldRefs>

Здесь мы не указываем ни тип данных, ни какой-либо другой мета-информации, а просто генерим ID (вот и пригодился On-line Guid Generator). Теперь создадим списки на основе наших типов содержимого. При добавлении нового элемента в проект выбираем List Definition From Content Type:
Далее выбираем сам тип и ставим галку "Add a list instance for this list definition":


Результат получаем примерно вот такой:
Теперь по порядку:
ListInstance
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <ListInstance Title="Департаменты"    <= Заголовок списка
                OnQuickLaunch="TRUE"    <= Отображение на панели быстрого запуска
                TemplateType="45782"    <= Id ListTemplate'а
                Url="Lists/departments" <= Url списка
                Description="">
  </ListInstance>
</Elements>
TemplateType мы берем из ListTemplate'а нашего списка. Visual Studio по-умолчанию начинает нумерацию с 10000, но лучше сразу изменить на нечто, наверняка не занятое другими разработчиками на проекте. И хорошо бы вести журнал учета этих идентификаторов.
Url нужен при создании Lookup полей.

ListTemplate
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    <ListTemplate

        Name="DepartmentList"
        Type="45782"
        BaseType="0"
        OnQuickLaunch="TRUE"
        SecurityBits="11"
        Sequence="410"
        DisplayName="Департаменты"
        Description=""
        Image="/_layouts/images/itgen.png"/>
</Elements>

Здесь нам интересны только атрибуты ID и Name. Они должны быть уникальны.

ListSchema

<?xml version="1.0" encoding="utf-8"?>

<List xmlns:ows="Microsoft SharePoint" Title="Employees" FolderCreation="FALSE" Direction="$Resources:Direction;" Url="Lists/ZhukPointContentType-EmployeeList" BaseType="0" xmlns="http://schemas.microsoft.com/sharepoint/">
  <MetaData>
    <ContentTypes>
      <ContentType ID="0x0100568056018ffd49a9ae1fd388c517ab64" Name="Employee" Group="ZhukPoint" Description="" Inherits="TRUE" Version="0">
        <FieldRefs>
          <FieldRef ID="a160c2699bbc402b9a501673e0ce5588" Name="Name" DisplayName="Имя" />
          <FieldRef ID="e74fa9434d7d484d99f51bb210f4c1c1" Name="Surname" DisplayName="Фамилия" />
          <FieldRef ID="8b867c02b39b49598785a094fa067321" Name="Position" DisplayName="Должность" />
          <FieldRef ID="c6964dd5d3df44fe94c6b3908c756f80" Name="Department" DisplayName="Департамент" />
        </FieldRefs>
      </ContentType>
      <ContentType ID="0x0100568056018ffd49a9ae1fd388c517ab6400082bbb65070f425abd85c5e8b78bf1a1" Name="VIP Employee" Group="ZhukPoint" Description="" Inherits="TRUE" Version="0">
        <FieldRefs>
          <FieldRef ID="34e00b99166b4639874a140634769d75" Name="Comment" DisplayName="Комментарий" />
        </FieldRefs>
      </ContentType>
    </ContentTypes>
    <Fields>
    </Fields>
    <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>
        </ViewFields>
        <Query>
          <OrderBy>
            <FieldRef Name="Modified" Ascending="FALSE">
            </FieldRef>
          </OrderBy>
        </Query>
 ...

Здесь мы указали два типа содержимого, используемого в нашем списке. В раздел List/Metadata/Fields добавляем поля из типов содержимого с обязательным указанием типа данных (!). Примерно вот так:
    <Fields>
      <Field ID="a160c2699bbc402b9a501673e0ce5588" Type="Text" Name="Name" DisplayName="Имя" />
      <Field ID="e74fa9434d7d484d99f51bb210f4c1c1" Type="Text" Name="Surname" DisplayName="Фамилия" />
      <Field ID="8b867c02b39b49598785a094fa067321" Type="Text" Name="Position" DisplayName="Должность" />
      <Field ID="34e00b99166b4639874a140634769d75" Type="Note" Name="Comment" DisplayName="Комментарий" />
      <Field ID="c6964dd5d3df44fe94c6b3908c756f80" Name="Department" DisplayName="Департамент"
             Type="Lookup"             <= Указываем, что поле у нас Lookup
             List="Lists/departments"  <= Url списка на который ссылаемся
             ShowField="Title"         <= Поле из которого берется значение
             Required="TRUE"           <= Обязательно ли требовать наличие значения
             Sealed="TRUE" />
    </Fields>



Теперь спускаемся ниже к разделу List/Metadata/Views/View[0]. Здесь мы просто добавим поля в представление по-умолчанию для удобства:


    <Views>
      <View BaseViewID="0" Type="HTML" MobileView="TRUE" TabularView="FALSE">
        ...
        <ViewFields>
          <FieldRef Name="LinkTitleNoMenu"></FieldRef>
          <FieldRef Name="Name"></FieldRef>
          <FieldRef Name="Surname"></FieldRef>
          <FieldRef Name="Position"></FieldRef>
          <FieldRef Name="Department"></FieldRef>
        </ViewFields>
       ...
Теперь развертываем наше решение и смотрим результат. Исходники можно взять тут.


2 комментария:

  1. Хотелось бы сделать поле которое бы не было видно в форме NewForm.aspx

    Field ID="a160c2699bbc402b9a501673e0ce5588" Type="Text" Name="Name" DisplayName="Имя" ShowInNewForm="False" -не помогает (

    ОтветитьУдалить
  2. Если посмотреть в Reflector'е, то увидим примерно следующее:

    public bool? get_ShowInNewForm()
    {
    string fieldAttributeValue = this.GetFieldAttributeValue("ShowInNewForm", 12);
    if (fieldAttributeValue == "TRUE")
    {
    return true;
    }
    if (!(fieldAttributeValue == "FALSE"))
    {
    return null;
    }
    return false;
    }

    поэтому надо просто значение атрибута перевести в верхний регистр

    ОтветитьУдалить