Общие сведения о модели преобразования страниц и ее настройке

Сердцем решения преобразования страницы является модель, которая передает преобразование: модель сообщает подсистеме, какие свойства веб-части важны, позволяет управлять этими свойствами и динамически выбирать сопоставление для веб-части. Модель преобразования страницы выражается в ФОРМАТЕ XML и поставляется со схемой, которая используется для проверки правильности модели.

Важно!

Модернизация SharePoint PnP является частью платформы PnP и постоянно развивается. См. заметки о выпуске, чтобы быть в курсе последних изменений. Если у вас возникнут проблемы, внесите данные о них в список проблем в GitHub на платформе PnP.

Высокоуровневая архитектура преобразования страницы

На приведенном ниже рисунке показаны 4 этапа преобразования страницы.

  1. Для начала необходимо сообщить подсистеме преобразования, как вы хотите преобразовать страницы. Для этого указывается модель преобразования страниц. Эта модель представляет собой XML-файл, в котором описывается, как требуется сопоставить каждую из классических веб-частей с современным эквивалентом. Модель содержит список применимых свойств и данные о сопоставлении для каждой классической веб-части. Дополнительные сведения см. в статье Общие сведения о модели преобразования страниц и ее настройке. Если вы хотите разобраться, как классические веб-части сравниваются с современными веб-частями, рекомендуем ознакомиться со статьей Возможности классических и современных веб-частей.
  2. Теперь следует проанализировать преобразуемую страницу. Подсистема преобразования разделит страницу на коллекцию веб-частей (текст вики-страниц преобразуется в одну или несколько веб-частей вики-текста) и попробует определить используемый макет.
  3. Сведений, полученных в ходе анализа на этапе 2, часто не хватает для сопоставления веб-части с современным эквивалентом, поэтому на этапе 3 мы дополним эти сведения, вызвав функции, которые принимают свойства, полученные на этапе 2, и создают новые свойства на основе свойств, введенных на этапе 2. После шага 3 у нас есть все необходимые сведения для сопоставления веб-части... Кроме того, при необходимости необходимо вызвать определенный селектор, чтобы понять, какое сопоставление нам потребуется, если одна классическая веб-часть может быть сопоставлена с несколькими современными конфигурациями.
  4. Последний шаг — создание и настройка современной страницы, после чего к ней добавляются сопоставленные современные веб-части.

преобразование страницы

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

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

  • BaseWebPart. Этот элемент содержит конфигурацию, которая применяется ко всем веб-частям. Например, он указывает, что свойство Title будет получено для всех веб-частей. Это также место, которое определяет сопоставление веб-частей по умолчанию: если веб-часть не имеет определенного сопоставления, подсистема вернется к этому сопоставлению, чтобы представить веб-часть на целевой странице.

  • AddOns: пользователю преобразования страницы может потребоваться применить пользовательскую логику для реализации своих потребностей, например преобразовать заданное свойство таким образом, чтобы оно могло работать с пользовательской веб-частью SPFX. Для этого платформа позволяет вам добавить сборки с функциями и селекторами. Для этого она просто определяет их в разделе AddOn, а затем ссылается на настраиваемые функции и селекторы, добавляя перед ними заданное имя, что позволяет использовать настраиваемый код при преобразовании страниц.

  • WebParts. Этот элемент содержит сведения для каждой веб-части, которую вы хотите преобразовать. Для каждой веб-части отображаются определения используемых свойств, выполняемые с ними функции, возможные сопоставления, которые определяют целевой объект преобразования, а также селектор, с помощью которого вы можете динамически выбрать необходимое сопоставление.

Дополнительные сведения смотрите в главах, которые вскоре появятся.

Определение элемента WebPart в модели преобразования страниц

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

      <!-- XsltListView web part -->
      <WebPart Type="Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c">
        <Properties>
          <Property Name="XmlDefinitionLink" Type="string" />
          <Property Name="ListUrl" Type="string" />
          <Property Name="ListId" Type="guid" Functions="{ListWebRelativeUrl} = ListAddWebRelativeUrl({ListId}); {ListServerRelativeUrl} = ListAddServerRelativeUrl({ListId})"/>
          <Property Name="Direction" Type="string"/>
          <Property Name="GhostedXslLink" Type="string" />
          <Property Name="DisableViewSelectorMenu" Type="bool"/>
          <Property Name="XmlDefinition" Type="string" Functions="{ListViewId} = ListDetectUsedView({ListId},{XmlDefinition})"/>
          <Property Name="SelectParameters" Type="string"/>
        </Properties>
        <!-- This selector outputs: Library, List  -->
        <Mappings Selector="ListSelectorListLibrary({ListId})">
          <Mapping Name="List" Default="true">
            <ClientSideText Text="You can map a source web part ({Title}) to a combination of modern web parts :-)" Order="10" />
            <ClientSideWebPart Type="List" Order="20" JsonControlData="&#123;&quot;serverProcessedContent&quot;&#58;&#123;&quot;htmlStrings&quot;&#58;&#123;&#125;,&quot;searchablePlainTexts&quot;&#58;&#123;&#125;,&quot;imageSources&quot;&#58;&#123;&#125;,&quot;links&quot;&#58;&#123;&#125;&#125;,&quot;dataVersion&quot;&#58;&quot;1.0&quot;,&quot;properties&quot;&#58;&#123;&quot;isDocumentLibrary&quot;&#58;false,&quot;selectedListId&quot;&#58;&quot;{ListId}&quot;,&quot;listTitle&quot;&#58;&quot;{Title}&quot;,&quot;selectedListUrl&quot;&#58;&quot;{ListServerRelativeUrl}&quot;,&quot;webRelativeListUrl&quot;&#58;&quot;{ListWebRelativeUrl}&quot;,&quot;webpartHeightKey&quot;&#58;4,&quot;selectedViewId&quot;&#58;&quot;{ListViewId}&quot;&#125;&#125;" />
          </Mapping>
          <Mapping Name="Library" Default="false">
            <ClientSideWebPart Type="List" Order="10" JsonControlData="&#123;&quot;serverProcessedContent&quot;&#58;&#123;&quot;htmlStrings&quot;&#58;&#123;&#125;,&quot;searchablePlainTexts&quot;&#58;&#123;&#125;,&quot;imageSources&quot;&#58;&#123;&#125;,&quot;links&quot;&#58;&#123;&#125;&#125;,&quot;dataVersion&quot;&#58;&quot;1.0&quot;,&quot;properties&quot;&#58;&#123;&quot;isDocumentLibrary&quot;&#58;true,&quot;selectedListId&quot;&#58;&quot;{ListId}&quot;,&quot;listTitle&quot;&#58;&quot;{Title}&quot;,&quot;selectedListUrl&quot;&#58;&quot;{ListServerRelativeUrl}&quot;,&quot;webRelativeListUrl&quot;&#58;&quot;{ListWebRelativeUrl}&quot;,&quot;webpartHeightKey&quot;&#58;4,&quot;selectedViewId&quot;&#58;&quot;{ListViewId}&quot;&#125;&#125;" />
          </Mapping>
        </Mappings>
      </WebPart>

Элемент Properties

Для каждой веб-части модель определяет свойства, которые могут быть полезны для настройки целевых современных веб-частей. Если вы пропустили определенные свойства, их можно просто вставить в модель. В некоторых свойствах вы увидите атрибут Functions: этот атрибут содержит одну или несколько функций (отдельные функции через ;) которые выполняются при сопоставлении исходной веб-части с целевой современной веб-частью. Вот как выглядит структура функции:

{Output} = FunctionName({Input1}, {Input2})

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

  • свойства, определенные в этой веб-части (например, {ListId});
  • свойства, определенные в базовой веб-части (например, {Title});
  • свойства, выведенные после выполнения предыдущей функции (например, {ListWebRelativeUrl});
  • стандартные свойства уровня сайта: {Host}, {Web}, {Site}, {WebId}, {SiteId}.

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

  • Одному строковому значению ({Output} в представленной модели). Оно будет добавлено в список свойств веб-частей с именем Output и значением, возвращенным после выполнения свойства FunctionName.
  • Список пар "ключ-значение" (строка словаря,строка<>): в этом случае каждая возвращаемая пара "ключ-значение" добавляется в список свойств веб-части.

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

Вот пример:

<Property Name="ListId" Type="guid" Functions="FormatGuid({ListId})"/>

Предположим, что свойство веб-части изначально содержит GUID в формате {AAFAD7D0-D57A-4BB1-8706-969A608C686B}. После выполнения свойства FormatGuid для значения будет задан результат FormatGuid (например, GUID без скобок AAFAD7D0-D57A-4BB1-8706-969A608C686B).

Если функция возвращает несколько значений, каждая возвращенная пара "ключ-значение", уже настроенная в качестве свойства веб-части, перезаписывает это значение свойства.

Примечание.

Все стандартные функции описаны в статье Функции и селекторы преобразования страниц

Элемент Mappings

Этот элемент определяет одну или несколько возможных целевых конфигураций для заданной исходной веб-части. Так как можно определить несколько целевых конфигураций, нужен механизм для определения используемого сопоставления:

  • Если элемент сопоставления содержит заполненный атрибут Selector, результат выполнения выбора селектора используется для поиска нужного сопоставления по имени (например, функция селектора ListSelectorListLibrary возвращает строку Library, в результате чего используется сопоставление с именем Library). Селекторы идентичны функциям, которые возвращают одно значение, поэтому вы можете ввести в функцию селектора любой атрибут веб-части.
  • Если имеется только одно сопоставление, оно используется при отсутствии результата селектора.
  • Если отсутствует результат селектора и при этом определено несколько сопоставлений, используется сопоставление с меткой Default.

Примечание.

Все стандартные селекторы описаны в статье Функции и селекторы преобразования страниц

Далее описан сам элемент Mapping.

Элемент Mapping

Внутри элемента Mapping можно иметь один или несколько элементов ClientSideText или ClientSideWebPart, как показано в приведенном ниже фрагменте кода. Обратите внимание, что функции можно запускать в сопоставлении, что удобно, если вы хотите выполнять обработку только в том случае, если выбрано определенное сопоставление.

<Mapping Name="List" Default="true" Functions="{SampleVariable} = SampleFunction({ListId})>
  <ClientSideText Text="You can map a source web part ({Title}) to a combination of modern web parts :-)" Order="10" />
  <ClientSideWebPart Type="List" Order="20" JsonControlData="&#123;&quot;serverProcessedContent&quot;&#58;&#123;&quot;htmlStrings&quot;&#58;&#123;&#125;,&quot;searchablePlainTexts&quot;&#58;&#123;&#125;,&quot;imageSources&quot;&#58;&#123;&#125;,&quot;links&quot;&#58;&#123;&#125;&#125;,&quot;dataVersion&quot;&#58;&quot;1.0&quot;,&quot;properties&quot;&#58;&#123;&quot;isDocumentLibrary&quot;&#58;false,&quot;selectedListId&quot;&#58;&quot;{ListId}&quot;,&quot;listTitle&quot;&#58;&quot;{Title}&quot;,&quot;selectedListUrl&quot;&#58;&quot;{ListServerRelativeUrl}&quot;,&quot;webRelativeListUrl&quot;&#58;&quot;{ListWebRelativeUrl}&quot;,&quot;webpartHeightKey&quot;&#58;4,&quot;selectedViewId&quot;&#58;&quot;{ListViewId}&quot;&#125;&#125;" />
</Mapping>

В приведенном выше примере исходная веб-часть XSLTListView сопоставлена с современной текстовой частью (ClientSideText) и современной веб-частью (ClientSideWebPart):

  • Атрибут Order позволяет определить, какая из них идет на первом месте.
  • Для веб-части ClientSideWebPart нужно указать Type. Если выбран тип Custom, также понадобится указать свойство ControlId для определения необходимой настраиваемой веб-части.
  • Свойства Text, JsonControlData и ControlId могут содержать токены в формате {Token}, которые заменяются фактическими значениями в среде выполнения. Каждый определенный токен должен поддерживать использование в качестве свойства или функции веб-части, как объяснялось раннее.

Определение элементов AddOns в модели преобразования страниц

С помощью надстроек вы можете вставить настраиваемую логику в модель сопоставления, выполнив следующие 2 действия:

  • создав настраиваемую сборку, в которой размещены настраиваемые функции и селекторы;
  • объявив эту настраиваемую сборку в элементах AddOns.

Создание настраиваемой сборки с функциями и селекторами

Чтобы создать собственные функции, вам потребуется вставить ссылку на сборку SharePoint.Modernization.Framework в проект, а затем создать класс, наследующий класс SharePointPnP.Modernization.Framework.Functions.FunctionsBase:

using Microsoft.SharePoint.Client;
using SharePointPnP.Modernization.Framework.Functions;
using System;

namespace Contoso.Modernization
{
    public class MyCustomFunctions: FunctionsBase
    {
        public MyCustomFunctions(ClientContext clientContext) : base(clientContext)
        {
        }

        public string MyListAddServerRelativeUrl(Guid listId)
        {
            if (listId == Guid.Empty)
            {
                return "";
            }
            else
            {
                var list = this.clientContext.Web.GetListById(listId);
                list.EnsureProperties(p => p.RootFolder.ServerRelativeUrl);
                return list.RootFolder.ServerRelativeUrl;
            }
        }

    }
}

Объявление настраиваемой сборки

Прежде чем использовать настраиваемые функции, их необходимо объявить в модели, добавив одну ссылку на библиотеку или класс в элемент AddOns:

<AddOn Name="Custom" Type="Contoso.Modernization.MyCustomFunctions" Assembly="Contoso.Modernization.dll" />

Можно также добавить такой код (обратите внимание на полный путь):

<AddOn Name="Custom" Type="Contoso.Modernization.MyCustomFunctions" Assembly="c:\transform\Contoso.Modernization.dll" />

Обратите внимание, что в приведенном выше примере каждое объявление имеет имя Custom.

Использование настраиваемых функций или селекторов

После определения сборки вы можете использовать функции и селекторы, ссылаясь на них с помощью имени, похожего на префикс Custom в этом примере:

<Property Name="ListId" Type="guid" Functions="{ListServerRelativeUrl} = Custom.MyListAddServerRelativeUrl({ListId})"/>