學習和配置頁面轉換模型

Justin-Liu發表於2018-08-13

部落格地址:http://blog.csdn.net/FoxDave

頁面轉換。解決方案的核心用於轉換的模型,模型會告訴引擎哪些web部件屬性是重要的,允許我們處理這些屬性,並動態為我們的web部件選擇對映。頁面轉換模型用XML表達,並通過結構清單檔案來驗證模型的正確性。

頁面轉換模型結構

我們開啟頁面轉換模型時,會看到如下三個部分:

  • BaseWebPart
    該元素包含應用到所有web部件的配置。例如:它描述了所有web部件都會獲取的”標題“屬性。它也是定義預設web部件對映的地方,如果一個web部件沒有定義對映,引擎就會訪問該預設對映去在客戶端頁面上展示web部件。
  • AddOns
    作為頁面轉換的使用者,我們可能需要應用自定義的邏輯來實現我們的需求。例如我們需要將一個既有的屬性轉換為能被我們的客戶端web部件接受的形式。框架支援這種做法,它允許我們新增我們自己的包含函式和選擇器的程式集,通過簡單地在AddOn部分中定義,之後通過在指定的名字上加字首來引用它們以使頁面轉換使用我們自定義的程式碼。
  • WebParts
    該元素包含我們想要轉換的每個web部件的資訊。對於每個web部件,我們可以找到要使用的屬性集的定義,在這些屬性上要執行的函式,可能的定義轉換目標的對映和我們動態選擇所需對映的選擇器。

轉換模型中Web部件的定義

接下來我們分析一下web部件是如何在頁面轉換模型中定義的,用下面的例子說明:

<!-- 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 client side controls :-)" 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>

屬性元素
對於每個web部件,模型定義了對配置目標客戶端web部件可能有用的屬性。如果我們遺漏了某個屬性,我們可以在模型中輕鬆地擴充套件出來。在一些屬性中可以看到函式型別的屬性,包含一到多個函式,用;分隔,會在源web部件對映到目的端客戶端web部件時執行。函式的解析如下:

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

函式可以具有一到多個輸入值,可以是:

  • web部件上定義的屬性,如{ListId}
  • 基礎web部件上定義的屬性,如{Title}
  • 之前函式執行產生的輸出屬性,如{ListWebRelativeUrl}
  • 預設的網站範圍的屬性,如{Host}、{Web}、{Site}、{WebId}、{SiteId}

函式在執行時它的輸出可能時:

  • 單一字串值:該值會以Output命名被新增到web部件的屬性列表中,屬性的值為執行函式後的返回值
  • 鍵值對的列表:此情況下鍵值對中的每一個元素都被新增到web部件的屬性列表中

如果函式沒有定義輸出引數,定義函式的web部件屬性的值將會被函式執行結果覆蓋。
讓我們用一個例子說明:

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

現在讓我們假定web部件屬性原先包含一個guid格式的值,如{AAFAD7D0-D57A-4BB1-8706-969A608C686B}。在執行完FormatGuid函式後,該值會被設定為執行格式化GUID函式後得到的結果值,如AAFAD7D0-D57A-4BB1-8706-969A608C686B。

如果函式返回了多個值,每一個返回的鍵值對會覆蓋已存在於web部件中的屬性。

對映集合元素
該元素定義一到多個對於給定源web部件的可能的目的端配置。既然我們可以定義多個目的端,我們就需要有一套機制去決定使用哪個對映:

  • 如果對映元素包含填充的選項屬性,選擇器執行的輸出被用來通過名稱找到正確的對映,如ListSelectorListLibrary返回”Library”字串表明使用名為”Library”的對映。選擇器是一對一的函式,返回單一的值,所以我們可以指定任意的web部件屬性作為輸入。
  • 如果僅有一個對映,在沒有選擇器結果時就選擇它。
  • 如果選擇器沒有結果且定義了多個對映,則使用預設的對映。

接下來我們講解對映元素本身。

對映元素
在對映元素中我們可以有一到多個ClientSideText或ClientSideWebPart元素,如下所示:

<Mapping Name="List" Default="true">
  <ClientSideText Text="You can map a source web part ({Title}) to a combination of client side controls :-)" 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>

上面的示例中,源web部件XSLTListViewweb被對映到目的端文字部件ClientSideText和一個目的端web部件ClientSideWebPart:

  • 使用Order屬性來指定哪個優先
  • 對於ClientSideWebPart我們需要指定web部件的Type,如果我們選擇Custom作為型別,我們還需要指定ControlId屬性來標識需要的自定義web部件。
  • Text、JsonControlData和ControlId屬性可以包含表單中的口令{Token},在執行時會被替換為真實的值。每個定義的口令需要能夠作為web部件屬性或函式的結果。

頁面轉換模型中AddOns的定義

Add-ons允許我們以下面的兩個步驟插入自己的邏輯到對映模型中:

  • 建立自定義的程式集來承載我們自定義的函式/選擇器
  • 在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”。

使用我們自定義的函式/選擇器
現在程式集已經定義完畢,我們可以使用我們的函式和選擇器了,通過自定義的名稱字首來引用如:

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

相關文章