自定義和擴展 SharePoint 2010 Server 功能區

瞭解構成 SharePoint 2010 服務器功能區的組件以及如何經過演練兩個功能區自定義項方案來自定義功能區。javascript

適用範圍: Microsoft SharePoint Foundation 2010 | Microsoft SharePoint Server 2010 | Microsoft Visual Studio 2010 中的 SharePoint 開發工具前端

目錄java

  • SharePoint 2010 Server 功能區簡介

  • SharePoint 2010 Server 功能區體系結構

  • 自定義 SharePoint 2010 Server 功能區

  • 自定義內置 SharePoint 2010 Server 功能區組件

  • 建立自定義 SharePoint 2010 Server 功能區組件

  • 自定義 SharePoint 2010 Server 功能區開發提示和技巧

  • 結論

  • 其餘資源

單擊以獲取代碼  下載本文附帶的代碼:MSDN 示例 - 自定義和擴展 SharePoint 2010 Server 功能區(該連接可能指向英文頁面)web

SharePoint 2010 Server 功能區簡介

隨着 2007 Microsoft Office system 的發佈,Microsoft 引入了一個稱做「功能區」的新用戶界面結構,它代替了之前的應用程序下拉菜單和工具欄。大量的調查研究代表,某些應用程序(例如,Microsoft Word)包含太多命令,致使用戶難以找到所需的命令,功能區正是爲解決這個問題而引入的。編程

功能區的前提是提供一個更加以結果爲導向的界面。用戶可將精力集中在他們執行的操做上,系統將僅顯示用戶可在特定時間執行的操做的命令。例如,當用戶明確地鍵入文本而且未選擇圖像或表時,沒有理由爲用戶提供與文檔中的表或圖像交互的命令。可是,經過使用「插入」選項卡,用戶可輕鬆添加表或圖片。僅在用戶選擇了表或圖片時,纔會出現新的命令結構。當表或圖片再也不是焦點時,這些命令將消失。數組

在 2007 Microsoft Office system 中,已在 Microsoft Word、Microsoft Excel 和 Microsoft PowerPoint 中實現功能區。Microsoft 在此基礎上進行了擴展,並已將功能區添加到全部 Microsoft Office 2010 應用程序(包括 Microsoft OneNote 20十、Microsoft Access 2010 和 Microsoft InfoPath 2010)。瀏覽器

相似於 Microsoft Office 客戶端,SharePoint 用戶在查找控件以完成其工做上遇到了相似的難題。命令在頁面中的多個位置存在,從「網站操做」菜單到管理 Web 部件或到列表中的「編輯控件塊」(ECB) 菜單。圖 1 演示了對 Windows SharePoint Services 3.0 網站中的用戶可用的全部菜單。緩存



圖 1. Windows SharePoint Services 3.0 中的菜單和命令
 

在 Microsoft SharePoint 2010 中,Microsoft 已將服務器功能區添加到 SharePoint,以解決用戶在使用 Microsoft Office 客戶端中的許多命令時遇到的難題。已將全部命令和菜單項從 SharePoint 中的主工做區向上推入始終固定到瀏覽器窗口頂部的功能區。2007 Microsoft Office system 的用戶或已實現功能區的其餘應用程序的用戶會發現,因爲 SharePoint 功能區與 Office 客戶端功能區很是類似,所以調節 SharePoint 功能區很是輕鬆。該功能區在外觀、工做方式和執行的操做上與 Office 功能區相似,而且具備與 Office 功能區相同的控件。Office 功能區和 SharePoint 服務器功能區之間的惟一差別與技術有關;例如,與在桌面(胖客戶端)體驗中同樣,難以在 Web(瘦客戶端)體驗中顯示不一樣的字體。安全

SharePoint 2010 中的功能區是基於與 Office 客戶端功能區相似的體系結構構建的。Microsoft 使用此體系結構在 SharePoint 2010 中實現默認功能區。此體系結構還容許第三方開發人員自定義和擴展 SharePoint 中包含的現有功能區組件以及建立命令結構。服務器

本文介紹了 SharePoint 服務器功能區的組件,以便您瞭解功能區的構造方式。而後,說明並演示了開發人員自定義和擴展功能區的方式。SharePoint Foundation 2010 通用參考中有一節專門介紹了功能區,幷包含各類自定義演練。在自定義功能區時,建議您將本文與 SharePoint Foundation 2010 通用參考(具體而言是 SharePoint Foundation 中的服務器功能區一節)配合使用。

SharePoint 2010 Server 功能區體系結構

默認功能區由 SharePoint 構建且基於做爲主安裝的一部分的單個文件。此文件是在路徑 {SharePoint Root}\TEMPLATE\GLOBAL\XML\CMDUI.XML 中找到的全局網站定義的一部分。此文件包含 SharePoint Foundation 2010 中的功能區組件(例如,「瀏覽」、「頁」、「列表」、「庫」和「文檔」選項卡)的定義。

雖然 CMDUI.xml 文件包含全部核心服務器功能區組件,這與對功能區實現其餘自定義的方式無關。SharePoint 功能用於實現對功能區的其餘更改。例如,Microsoft SharePoint Server 2010 包括許多須要功能區修改的任務,例如,與「企業內容管理」、「表單服務」和商業智能相關的任務。全部這些更改都是經過使用 SharePoint 功能實現的。SharePoint 開發人員還可經過使用功能來自定義功能區,如本文後面的建立自定義 SharePoint 2010 Server 功能區組件中所述。

SharePoint 2010 擴展了功能架構(具體而言爲 <CustomAction /> 元素),使其成爲全部功能區自定義項的工具。經過將 Location 屬性設置爲 CommandUI.Ribbon 並添加一個 <CommandUIExtension /> 子元素,能夠作到這一點。SharePoint 2010 SDK 概述了服務器功能區 XML

如下各節說明了功能區的兩大核心部分:構成視覺體驗的組件以及在單擊功能區中某個控件時運行的代碼。

SharePoint 2010 Server 功能區組件

SharePoint 2010 服務器功能區包含各類組件,如圖 2 所示。



圖 2. SharePoint 2010 Server 功能區組件


圖中的標註號指向如下特定組件:

  1. 選項卡



  2. 控件

  3. 上下文選項卡組

後面幾節簡要介紹了這些組件及其使用。

SharePoint 2010 Server 功能區上的選項卡

選項卡是服務器功能區的根。它們包含一個或多個組,幷包含類似的功能。例如,在圖 2 中,當前選定的「頁」選項卡包含與使用當前頁相關的功能。

SharePoint 2010 Server 功能區上的上下文選項卡組

上下文選項卡組用於提供當前上下文的非全局功能(例如頁)。它們僅在遇到某些狀況時出現且包含一個或多個選項卡。

例如,圖 2 中的功能區演示「庫工具」上下文選項卡組,該組僅在文檔庫中顯示或(在此示例中)當選中與文檔庫關聯的當前頁面上的「列表視圖 Web 部件」時顯示。

上下文選項卡組會在功能和菜單選項不可用時爲用戶隱藏它們,並在功能和菜單選項可用時爲用戶顯示它們。上下文選項卡組的其餘示例包括在編輯 wiki 頁時出現的「編輯工具」上下文選項卡組,或在編輯模式下選中某張圖片時出現的「圖片工具」上下文選項卡組。

SharePoint 2010 Server 功能區上的組

功能區中的每一個選項卡均包含一個組或一系列組。組用於將控件與類似功能關聯。每一個組均與一個模板關聯,該模板根據功能區縮放定義組的佈局及其顯示方式。功能區縮放是指功能區中有太多控件要顯示的狀況,例如,當瀏覽器未處於全屏最大化顯示狀態而只是處於窗口狀態時。

SharePoint 2010 Server 功能區上的組模板

組模板用於爲組中的控件定義不一樣的佈局選項。Microsoft 在 CMDUI.xml 文件中包含 29 個組模板(若要查找這些模板,請在此文件的結尾搜索元素 <RibbonTemplates />)。

SharePoint 2010 Server 功能區上的控件

若是用戶未選擇或單擊任何項,則功能區將是不完整的。控件是用戶可與之交互的功能區內部的項。控件駐留在組中,其中包括按鈕、切換按鈕、複選框、文本框和許多其餘控件。有關全部可用控件的完整列表,請參閱服務器功能區的體系結構

每一個控件定義包含一個 Command 屬性,在單擊或選中該屬性時,會告知功能區基礎結構要執行的操做。

SharePoint 2010 中的服務器功能區命令

服務器功能區使用命令處理用戶執行的單擊或選擇操做。熟悉命令基礎結構在 Windows Presentation Foundation 或 Microsoft Silverlight 4 中的工做方式的用戶會發現它等同於服務器功能區命令基礎結構。每一個命令都進行了命名,並在控件中引用相應的名稱。最重要的是,這些命令包含兩條很是重要的詳細信息:

  • 當前命令是否可用  例如,「刪除」命令僅在文檔庫中或選中文檔時可用。

  • 應運行的代碼  例如,「刪除」命令可能會使用 SharePoint 2010 客戶端對象模型來刪除列表中的項、顯示已刪除文檔通知並在頁面上刷新列表視圖 Web 部件。

主題服務器功能區的體系結構包含與命令基礎結構的工做方式相關的其餘詳細信息。

經過使用 ECMAScript(JavaScript、JScript) 編寫服務器功能區中的命令。可經過兩種方式實現命令:

  • 經過命令 UI 處理程序

  • 經過頁面組件

如下各節中對這兩個選項進行了說明,並討論了每一個選項的優缺點。一般,簡單且相對較小的命令適用於命令 UI 處理程序選項。可是,較爲複雜且須要實現大量 ECMAScript 的命令可能更適用於頁面組件。本文後面的文檔庫示例中使用的示例功能區自定義項演示如何使用每種技術來執行徹底相同的操做。

使用命令 UI 處理程序實現服務器功能區命令

命令 UI 處理程序是經過結合使用聲明性標記和 ECMAScript 來實現的。在定義功能區自定義項(使用 <CommandUIExtension /> 元素進行定義)的同一 Feature 元素清單中使用 <CommandUIHandler /> 元素定義這些處理程序。此元素包含如下三個屬性:

  • Command  將在控件中引用的命令名稱。

  • CommandAction  觸發該命令時執行的 ECMAScript。

  • EnabledScript  ECMAScript,服務器功能區命令基礎結構調用它來肯定該命令是否可用。此腳本應返回一個布爾值,若是該命令可用,則爲 TRUE;若是該命令不可用,則爲 FALSE。若是該命令不可用,則功能區基礎結構會將功能區中的該命令灰顯,而且在用戶選擇該命令時不調用它。

使用命令 UI 處理程序的優勢

一般,對於大多數開發人員而言,命令 UI 處理程序更易於編寫和管理。因爲這些處理程序是以聲明方式定義的,所以功能區框架會將腳本添加到其中的引用控件須要命令的任何頁面。

使用命令 UI 處理程序的缺點

命令 UI 處理程序的缺點之一是,當它們包含大量自定義 ECMAScript 時會變得難以管理、調試和進行故障排除。此外,因爲這些處理程序會做爲內聯腳本塊添加到每一個頁面中,所以沒法經過瀏覽器對其進行緩存,而且每次都必須下載,從而增長了總體頁權重。

使用頁面組件實現服務器功能區命令

除了使用命令 UI 處理程序外,還可使用頁面組件。頁面組件是一個在外部腳本庫 (.js) 文件中定義的 ECMAScript 對象。該對象實現了幾個屬性和方法,它們將告知服務器功能區命令基礎結構如何初始化該對象、該對象可處理哪些命令以及某個特定命令是否可用,並可在頁面組件接收焦點或失去焦點時作出響應。

必須將此腳本文件添加到顯示功能區自定義項的同一頁面中。可經過多種方法來實現這一點。第一種方法是,使用 SharePoint 2010 中的新 <CustomAction ScriptSrc="" /> 功能,根據功能的範圍將庫添加到網站、網站集、Web 應用程序或服務器場中的全部頁面。另外一種方法是,從自定義應用程序或網站頁面 (.aspx)、自定義用戶控件 (.ascx) 或自定義服務器控件內的託管代碼添加腳本。如下代碼示例將向 Web 部件內的頁面添加頁面組件文件。

複製
private void LoadAndActivateRibbonContextualTab() {
  SPRibbon ribbon = SPRibbon.GetCurrent(this.Page);
  // Ensure ribbon exists.
  if (ribbon != null) {
    // Load dependencies if not already on the page.
    ScriptLink.RegisterScriptAfterUI(this.Page, "SP.Ribbon.js", false, true);

    // Load and activate contextual tab.
    ribbon.MakeTabAvailable("Ribbon.PropertyChangerTab");
    ribbon.MakeContextualGroupInitiallyVisible("Ribbon.WebPartContextualTabGroup", string.Empty);
  }
}

使用頁面組件的優勢

因爲全部 ECMAScript 都位於外部腳本庫中,所以更易於對頁面組件(而非命令 UI 處理程序)進行管理、故障排除和調試(Microsoft Visual Studio 2010 腳本調試器可設置斷點並附加到庫)。另外,因爲它是一個外部庫,所以瀏覽器可緩存該庫,而無需每次在頁面上引用它時向它發出請求。

還可利用頁面組件更好地控制命令,由於它們可經過接收或丟失焦點來啓用或禁用頁面組件,並處理上述每種狀況下發生的事件。

另外,因爲它們是外部庫,所以,一個頁面組件可處理多個控件的命令,並可在各類功能區自定義項中重用。

使用頁面組件的缺點

相對於使用命令 UI 處理程序,使用頁面組件的一個缺點是須要大量腳本。這主要是由於開發人員在頁面上構建、註冊和初始化一個腳本對象。另外,不熟悉面向對象的 ECMAScript 技術的開發人員會發現要作到這一點會有點難度。

使用頁面組件的另外一個缺點是,必須將其添加到頁面,由於這不是由功能區命令基礎結構處理的。

自定義 SharePoint 2010 Server 功能區

當開發人員但願自定義 SharePoint 服務器功能區時,會爲其提供兩個選項。以聲明方式或以編程方式應用自定義項。使用功能實現本文前面所述的聲明性方法;具體而言,帶 <CommandUIExtensions /> 子元素的 <CustomAction /> 元素。

編程方法包括將聲明性構造做爲字符串添加到服務器功能區對象中。本文的其他內容將重點說明聲明性方法,由於也可將這些技術應用於編程方法。SharePoint 2010 SDK 包含有關以編程方式自定義功能區的演練:演練:使用上下文選項卡建立自定義 Web 部件

自定義內置 SharePoint 2010 Server 功能區組件

開發人員可經過三種方式自定義功能區:

  • 向功能區添加組件(選項卡、上下文選項卡組、組和控件)。

  • 在功能區中修改現有組件。

  • 從功能區中刪除現有組件。

能夠聲明方式執行全部這三個選項。服務器功能區 XML 演示了不一樣的元素。服務器功能區的聲明性自定義項演示如何向功能區添加三個經常使用組件。

修改和移除組件(例如,選項卡、組和控件)的方式與修改和移除相同架構元素的方式很相似。經過重複元素的 ID 並替換其內容來修改元素,這與內容佔位符在 Microsoft ASP.NET 2.0 母版頁中的工做方式相似。移除操做與修改操做相同,只不過容器保留爲空。有關詳細信息,請參閱服務器功能區的聲明性自定義項

建立自定義 SharePoint 2010 Server 功能區組件

如下兩節演示如何自定義 SharePoint 2010 服務器功能區。這兩個演練都使用了各類技術,並對每一個組件進行了詳細說明。有關這兩個演練的示例代碼,請參閱 MSDN 示例 - 自定義和擴展 SharePoint 2010 Server 功能區(該連接可能指向英文頁面)。此示例代碼只須要一個 SharePoint Foundation 2010 網站集。

第一個示例爲 WebPartRibbonContextualTab(如圖 3 所示),它演示如何建立使用如下功能區自定義項的自定義 Web 部件:

  • 上下文選項卡組

  • 自定義選項卡

  • 自定義組

  • 命令 UI 處理程序

  • 僅當 Web 部件位於頁面上時激活上下文選項卡組

  • 單擊功能區上的按鈕時觸發並處理服務器端回發。



圖 3. 帶上下文選項卡組的 Web 部件


第二個示例爲 ApplyDocumentPrefixRibbon(如圖 4 所示),它演示如何實現如下自定義項和技術:

  • 現有功能區選項卡中的自定義組。

  • 具備不一樣佈局選項的自定義組模板。

  • 執行相同操做的兩個自定義命令,只不過其中一個命令是經過命令 UI 處理程序實現的,而另外一個命令實現自定義頁面組件:

    • 除非選中庫中的一個或多個文檔,不然將禁用命令。

    • 單擊時,命令將打開一個對話框,傳遞選定文檔並根據用戶輸入執行操做。

    • 在對話框的工做完成後,該對話框將關閉,同時命令將顯示一條通知消息並刷新列表視圖 Web 部件而非整個頁面。

  • 按條件加載頁面組件的自定義服務器控件。



圖 4. 具備頁面組件的自定義組


Gg552606.note(zh-cn,office.14).gif註釋:

爲了便於閱讀,已略去示例代碼中的某些標記。有關完整代碼引用,請參閱 MSDN 示例 - 自定義和擴展 SharePoint 2010 Server 功能區(該連接可能指向英文頁面)

 

如何:建立支持 Web 部件的上下文選項卡並利用回發

在本示例中,在將 Web 部件添加到頁面時,將顯示上下文選項卡,如以前的圖 3 所示。此選項卡包含提供幾個按鈕的兩個組。第一個組中的按鈕不執行任何操做,而只演示如何使用默認模板之一。可是,「Write to Web Part via PostBack」按鈕會發布一次回發。Web 部件包含用於檢查按鈕是否已發佈回發的代碼,若是出現此狀況,則向 Web 部件的內容中添加一些文本。

步驟 1:建立 Web 部件

第一個步驟是建立 Web 部件。使用新的 Microsoft Visual Studio 2010 中的 SharePoint 開發工具建立一個 SharePoint 項目,並向該項目中添加一個 Web 部件 SharePoint 項目項。CreateChildControls 方法執行兩個操做:將一些文本寫入 Web 部件,並在引起特定回發事件時調用方法以處理狀況,如如下代碼中所示。

複製
public class RibbonizedWebPart : WebPart {
  private string POSTBACK_EVENT = "RibbonizedWebPartPostback";

  protected override void CreateChildControls() {
    this.Controls.Add(
      new LiteralControl(
        "<em>Ribbonized Web Part contents go here</em>"
      )
    );

    // Handle postback from ribbon. 
    HandleRibbonPostback();
  }
}

接下來,建立處理回發事件的方法。若是它是一個特定的回發事件,則它會將其餘一些文本寫入 Web 部件的內容,如如下代碼所示。

複製
private void HandleRibbonPostback() {
  if (this.Page.Request["__EVENTTARGET"] == POSTBACK_EVENT) {
    this.Controls.Add(
      new LiteralControl(
        "<p>Responding to postback event from ribbon.</p>"
      )
    );
  }
}

最後一步是,實現將向頁面中添加自定義上下文選項卡的代碼。可從 Web 部件的生命週期的 OnPreRender 階段實現這一點。它必須得到對服務器功能區的引用,並確保已在頁面上加載腳本依賴項。最後,爲了顯示上下文選項卡,它使 ID 爲 Ribbon.PropertyChangerTab 的選項卡可用,並告知功能區在加載頁面時使 ID 爲 Ribbon.WebPartContextualTabGroup 的上下文選項卡可用,如如下代碼所示。

複製
protected override void OnPreRender(EventArgs e) {
  LoadAndActivateRibbonContextualTab();
  base.OnPreRender(e);
}

private void LoadAndActivateRibbonContextualTab() {
  SPRibbon ribbon = SPRibbon.GetCurrent(this.Page);
  // Ensure ribbon exists.
  if (ribbon != null) {
    // Load dependencies if not already on the page.
    ScriptLink.RegisterScriptAfterUI(this.Page, 
      "SP.Ribbon.js", false, true);

    // Load and activate contextual tab.
    ribbon.MakeTabAvailable("Ribbon.PropertyChangerTab");
    ribbon.MakeContextualGroupInitiallyVisible(
      "Ribbon.WebPartContextualTabGroup", string.Empty);
  }
}

步驟 2:建立服務器功能區組件自定義項

建立 Web 部件後,下一步是建立服務器功能區組件自定義項。爲此,您建立一個上下文選項卡組,一個帶兩個組的選項卡和幾個控件。

Microsoft Visual Studio 2010 中的 SharePoint 開發工具不包含用於自定義功能區的 SharePoint 項目項模板。然而,通用的 SharePoint 項目項「空元素」可用於包含功能區自定義項,所以向項目中添加一個新的空元素。

步驟 2.1:向 Element 中添加核心功能區標記

在項目的新「Element」SharePoint 項目項中,向 element.xml 文件中添加如下標記。

XML
複製
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction Id="WebPartContextualTabs" Location="CommandUI.Ribbon">
    <CommandUIExtension>
      <CommandUIDefinitions />
      <CommandUIHandlers />
    </CommandUIExtension>
  </CustomAction>
</Elements>

這將告知 SharePoint 如下內容:

  • 元素清單包含適用於任何位置的功能區 (<CustomAction Location="CommandUI.Ribbon" />) 的功能區自定義項。有五個針對 Location 屬性的選項。開發人員能夠經過其餘選項指定,在顯示列表視圖 Web 部件時或者在某個項的顯示、新建或編輯表單上應顯示自定義項。另外,RegistrationTypeRegistrationId 容許開發人員對自定義項的顯示位置進行更精確地定位。例如,開發人員可面向特定的內容類型。服務器功能區 XML 中列出了全部選項。

  • 還包括功能區自定義項的基本結構。

步驟 2.2:添加新的上下文選項卡組

接下來,添加將建立上下文選項卡組的如下標記。

XML
複製
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction Id="WebPartContextualTabs" Location="CommandUI.Ribbon">
    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition 
                Location="Ribbon.ContextualTabs._children">
          <ContextualGroup Id="Ribbon.WebPartContextualTabGroup"
                ContextualGroupId="WebPartContextualTab"
                Title="Ribbonized Web Part Tools"
                Sequence="150"
                Color="Green"
                Command="WebPartContextualTab.OnEnableContextualTab">
          </ContextualGroup>
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers />
    </CommandUIExtension>
  </CustomAction>
</Elements>

<CommandUIDefinition> Location 屬性告知功能區向其中的上下文選項卡添加如下內容,即一個或多個 <ContextualGroup /> 元素。

<ContextualGroup /> 元素定義新組。它具備一個與上下文組的名稱匹配的 Id 屬性,Web 部件的代碼告知功能區在最初加載頁面時使該上下文組可見。

Sequence 屬性告知 SharePoint 此上下文組的順序(當存在其餘上下文組時)。爲 SharePoint 上下文組給定的序列將從 100 開始(即「編輯工具」上下文組),而後按 100 遞增。所以,若是存在「編輯工具」組,則上下文組可能會顯示在第一個或第二個位置。有關如何查找其餘上下文組的名稱和序列的信息,請參見本文後面的自定義 SharePoint 2010 Server 功能區開發提示和技巧一節。

Command 屬性將此組與命令名稱關聯。在某些狀況下,當選中此選項卡組時,運行腳本可能會頗有用。但在此狀況下,命令(稍後實現)用於告知功能區激活上下文組的時間。若是未實現,則一旦用戶單擊任何項,就會促使功能區隱藏自定義組。

步驟 2.3:向上下文選項卡組添加選項卡

在建立上下文選項卡組後,添加如下標記以添加新選項卡並定義最大大小布局組模板。

XML
複製
<CommandUIDefinitions>
  <CommandUIDefinition Location="Ribbon.ContextualTabs._children">
    <ContextualGroup Id="Ribbon.WebPartContextualTabGroup" ... >
      <Tab Id="Ribbon.PropertyChangerTab" 
           Title="Tools" Sequence="501">
        <Scaling Id="Ribbon.PropertyChangerTab.Scaling">
          <MaxSize Id="Ribbon.PropertyChangerTab.MaxSize"
             GroupId="Ribbon.PropertyChangerTab.PropertyGroup"
             Size="LargeLarge" />
          <MaxSize Id="Ribbon.PropertyChangerTab.MaxSize" ... />
        </Scaling>
      </Tab>
    </ContextualGroup>
  </CommandUIDefinition>
</CommandUIDefinitions>

在圍繞 <MaxSize /> 元素的此代碼段中,須要注意兩點。它將稍後定義的組(經過 GroupId 屬性)與模板中定義的佈局選項 LargeLarge(經過 Size 屬性)關聯。

步驟 2.4:向選項卡添加組

如今,經過添加如下標記向新選項卡添加組。

XML
複製
<CommandUIDefinitions>
  <CommandUIDefinition Location="Ribbon.ContextualTabs._children">
    <ContextualGroup Id="Ribbon.WebPartContextualTabGroup" ... >
      <Tab Id="Ribbon.PropertyChangerTab" ... >
        <Scaling Id="Ribbon.PropertyChangerTab.Scaling" ... >
        </Scaling>
        <Groups Id="Ribbon.PropertyChangerTab.Groups">
          <Group Id="Ribbon.PropertyChangerTab.PropertyGroup" ... >
            ...
          </Group>
          <Group Id="Ribbon.PropertyChangerTab.PostBackGroup"
                 Title="PostBack" Sequence="25"
                 Template="Ribbon.Templates.Flexible2">
          </Group>
        </Groups>
      </Tab>
    </ContextualGroup>
  </CommandUIDefinition>
</CommandUIDefinitions>

雖然本示例中有兩個組,但此代碼列表中僅顯示第二個組。請注意,組包含 Id 屬性,該屬性與以前已添加的 <MaxSize GroupId="" /> 元素匹配。

另請注意,組使用的是一個名爲 Ribbon.Templates.Flexible2 的模板。該模板包含在內置 CMDUI.xml 功能區聲明中。在功能區自定義項功能中定義自定義組時,Microsoft 建議開發人員建立其本身的組模板,而不是使用提供的組模板之一。這樣作的緣由是,SharePoint 不會爲每一個頁面請求加載整個功能區;而只加載當前上下文所需的部分功能區。這包括組模板。所以,若是開發人員依賴內置組模板,則能夠不爲當前頁面加載模板且不顯示其功能區自定義項。

對於此示例自定義項,因爲這是 Web 部件的一部分,而且 Web 部件必須位於 Web 部件頁上,所以,假定將加載此模板,由於它是每一個 Web 部件頁上都具備的「頁面」選項卡的一部分。

有關如何查找其餘模板的名稱的信息,請參閱本文後面的自定義 SharePoint 2010 Server 功能區開發提示和技巧

步驟 2.5:向組添加控件

定義功能區自定義項的可見部分的最後一個步驟是向組添加控件。將如下標記添加到第二個組(請參閱 MSDN 示例 - 自定義和擴展 SharePoint 2010 Server 功能區(該連接可能指向英文頁面),以將按鈕添加到第一個組)。

XML
複製
<CommandUIDefinitions>
  <CommandUIDefinition Location="Ribbon.ContextualTabs._children">
    <ContextualGroup Id="Ribbon.WebPartContextualTabGroup" ... >
      <Tab Id="Ribbon.PropertyChangerTab" ... >
        <Scaling Id="Ribbon.PropertyChangerTab.Scaling" ... >
        </Scaling>
        <Groups Id="Ribbon.PropertyChangerTab.Groups">
          <Group Id="Ribbon.PropertyChangerTab.PropertyGroup" ... >
            ...
          </Group>
          <Group Id="Ribbon.PropertyChangerTab.PostBackGroup" ... >
            <Controls Id="Ribbon.PropertyChangerTab.PropertyGroup.Controls">
              <Button Id="Ribbon.PropertyChangerTab.PropertyGroup.GeneralDialogButton"
                      LabelText="Write to Web Part"
                      Command="WebPartContextualTabs.OnPostback"
                      TemplateAlias="o1"
                      Sequence="15"
                      Image16by16="/_layouts/Images/WebPartRibbonContextualTab/16x16Placeholder.png"
                      Image32by32="/_layouts/Images/WebPartRibbonContextualTab/32x32Placeholder.png" />
            </Controls>
          </Group>
        </Groups>
      </Tab>
    </ContextualGroup>
  </CommandUIDefinition>
</CommandUIDefinitions>

此標記將向具備寫入 Web 部件的標籤的組中添加一個新按鈕控件。在單擊此按鈕時,它將觸發 Command=""TemplateAlias 屬性告知服務器功能區定義的組模板將按鈕放置到的位置。最後,佈局將使用兩個圖像屬性來顯示處於不一樣狀態的功能區圖標。這些圖像可指向服務器上的任何圖像。在此示例中,它們指向已添加到項目中的圖像。

步驟 3:建立服務器功能區命令

最後一個步驟是,定義已在功能區組件中引用的兩個命令。將如下標記添加到元素清單。

XML
複製
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction Id="WebPartContextualTabs" Location="CommandUI.Ribbon">
    <CommandUIExtension>
      <CommandUIDefinitions>
        ...
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler Command="WebPartContextualTab.OnEnableContextualTab"
          CommandAction=""
          EnabledScript="return true;" />
        <CommandUIHandler Command="WebPartContextualTabs.OnPostback"
          CommandAction="javascript:__doPostBack('RibbonizedWebPartPostback','');" />
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>
</Elements>

第一個 <CommandUIHandler /> 具備一個與上下文選項卡組關聯的命令。如前所述,此命令僅用來告知 Server 功能區其激活時間,而不執行任何其餘操做。爲了在功能區中不顯示此命令,其 EnabledScript 屬性將始終返回 TRUE。所以,若是上下文選項卡組位於頁面上(此時 Web 部件也位於頁面上,由於 Web 部件將處理其激活),則它決不會消失。

第二個 <CommandUIHandler /> 與按鈕控件關聯。當單擊該控件時,將觸發一個包含名爲 RibbonizedWebPartPostBack 的事件的回發。回想一下,Web 部件中的代碼正在偵聽該事件名稱,並在發現該名稱時向 Web 部件中添加文本。

步驟 4:部署和測試

在保存全部更改後,經過在 Visual Studio 2010 中按 F5,或經過在「調試」菜單上單擊「開始調試」來部署自定義 Web 部件。

在加載初始網頁時,您會發現未顯示上下文選項卡,如圖 5 所示。



圖 5. 不具備上下文選項卡組的調試網站的主頁


如今,經過選擇「頁面」選項卡,而後單擊「編輯」,可將頁面置於編輯模式中。將頁面上的 Web 部件插入默認位置。在從新加載頁面時,您會發現,上下文選項卡和 Web 部件都是可見的,如圖 6 所示。



圖 6. 上下文選項卡和 Web 部件是可見的


經過選擇自定義上下文選項卡組中的「工具」選項卡,而後單擊相應的按鈕來測試回發。頁面應被刷新並在 Web 部件中包含其餘文本,如圖 7 所示。



圖 7. 響應來自功能區的回發的 Web 部件


還請注意,上下文選項卡組將做爲第二個上下文選項卡組顯示在頁面上。這是由於,頁面仍處於編輯模式中,而且序列已設置爲 150(大於編輯工具序列)。在頁面退出編輯模式後,自定義上下文組應顯示在第一個位置。

演練:向文檔選項卡中添加按鈕並有條件地啓用它們

本演練中的示例演示如何將帶按鈕的新組添加到現有功能區。在部署項目時,它會在「文檔」選項卡中註冊一個新組,該組是「庫工具」上下文選項卡組的一部分。此上下文選項卡組僅在用戶與文檔交互或位於文檔庫中時顯示。圖 8 演示了不帶功能區的工做組網站主頁,但在選中共享文檔庫時(如圖 9 所示),顯示的上下文選項卡組會帶自定義項。



圖 8. 未選定文檔庫的工做組網站主頁


 



圖 9. 已選定文檔庫的工做組網站主頁


最初,三個按鈕中有兩個按鈕未啓用。除非選定一個或多個文檔,不然將啓用與按鈕關聯的命令,如圖 10 所示。



圖 10. 在選定文檔時啓用的功能區按鈕


在單擊後面兩個按鈕(即「Apply Prefix w/ CommandUI Handler」和「Apply Prefix w/ Page Component」)時,將執行相同的操做。但從其名稱可瞭解,一個按鈕將使用命令 UI 處理程序,而另外一個按鈕將使用自定義頁面組件。在單擊按鈕時,它們會收集頁面上全部選定文檔的列表,並將這些文檔傳遞給一個新對話框,如圖 11 所示。此對話框容許用戶向全部選定文檔的名稱添加前綴。



圖 11. 從功能區自定義項引起的自定義對話框


在單擊「Set Prefix」按鈕時,對話框將更新全部文檔的名稱,而後關閉。根據對話框是經過單擊「Set Prefix」按鈕仍是經過單擊「Cancel」來關閉的,命令會發出一條通知消息,而後刷新頁面上的列表視圖 Web 部件,以更新列表內容。

步驟 1:建立服務器功能區組件自定義項

第一步是,使用 Microsoft Visual Studio 2010 中的 SharePoint 開發工具建立一個新的 SharePoint 空項目。在建立該項目時,向該項目中添加一個將包含功能區自定義項的新的「空元素」項目項。

步驟 1.1:向 Element 中添加核心功能區標記

在元素清單內添加如下標記。

XML
複製
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction Id="Ribbon.Documents.ApplyDocumentPrefix" Location="CommandUI.Ribbon">
    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition Location="Ribbon.Documents.Groups._children">
          <Group Id="Ribbon.Documents.ApplyDocumentPrefix"
                 Title="Document Naming Tools"
                 Description="Document Naming Tools Description"
                 Sequence="25"
                 Template="Ribbon.Templates.MsdnTemplate">
          </Group>
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers />
    </CommandUIExtension>
  </CustomAction>
</Elements>

這將向「文檔」選項卡的一個名爲「Document Naming Tools」的組集合中添加一個新組,如 <CommandUIDefinition Location="Ribbon.Documents.Groups._children"> 所示。該組包含一個由 25 個項組成的序列。內置 SharePoint 2010 服務器功能區中的組的編號從數字 10 開始按 10 遞增。這意味着,此處定義的自定義組將在第三個位置顯示。

另外,該組將不會使用某個現有組模板,而將使用一個自定義組模板。

步驟 1.2:添加自定義組模板

添加如下標記以向功能區添加自定義組。

XML
複製
<CommandUIExtension>
  <CommandUIDefinitions>
    <CommandUIDefinition Location="Ribbon.Documents.Groups._children">
      <Group Id="Ribbon.Documents.ApplyDocumentPrefix" ... > 
        ...
      </Group>
    </CommandUIDefinition>
    <CommandUIDefinition Location="Ribbon.Templates._children">
      <GroupTemplate Id="Ribbon.Templates.MsdnTemplate">
        <Layout Title="MsdnHorizontal">
          <Section Type="OneRow">
            <Row>
              <ControlRef DisplayMode="Large" TemplateAlias="o1" />
              <ControlRef DisplayMode="Large" TemplateAlias="o2" />
              <ControlRef DisplayMode="Large" TemplateAlias="o3" />
            </Row>
          </Section>
        </Layout>
        <Layout Title="MsdnVertical">
          <Section Type="ThreeRow">
            <Row><ControlRef DisplayMode="Medium" TemplateAlias="o1" /></Row>
            <Row><ControlRef DisplayMode="Medium" TemplateAlias="o2" /></Row>
            <Row><ControlRef DisplayMode="Medium" TemplateAlias="o3" /></Row>
          </Section>
        </Layout>
       <Layout Title="MsdnVerticalTextOnly">
          <Section Type="ThreeRow">
            <Row><ControlRef DisplayMode="Menu" TemplateAlias="o1" /></Row>
            <Row><ControlRef DisplayMode="Menu" TemplateAlias="o2" /></Row>
            <Row><ControlRef DisplayMode="Menu" TemplateAlias="o3" /></Row>
          </Section>
        </Layout>
      </GroupTemplate>
    </CommandUIDefinition>
  <CommandUIDefinitions>
  <CommandUIHandlers />
</CommandUIExtension>

此模板(即「Ribbon.Templates.MsdnTemplate」)包含三個不一樣的佈局。每一個 <Layout /> 具備一個 Title 屬性,<MaxSize /> 元素或 <Scale /> 元素中引用了該屬性。這會告知功能區要用於佈局的模板。每一個 <Layout /> 元素均具備一個 <Section />,它使用 Type 屬性定義組的呈現方式。這能夠是 4 個用於呈現組的選項之一,這些選項包括使用一行、使用兩行、使用三行或使用分隔線。有關詳細信息,請參閱 Section 元素

<Section /> 包含一個或多個 <Row /> 元素,這些元素定義佈局中的每一個行。<Row /> 元素包含充當控件的佔位符的 <ControlRef /> 元素。DisplayMode 屬性告知功能區如何使用文本標籤、大圖標、小圖標或 ControlRef 元素的架構中定義的其餘選項之一來呈現控件。TemplateAlias 屬性用於觸發特定控件放置。在向組添加控件時,每一個控件的 TemplateAlias 屬性將與這些 TemplateAlias 屬性之一匹配以準確指定控件的放置位置。

如今添加如下標記,以告知功能區如何經過使用已定義模板中的佈局之一來呈現組。

XML
複製
<CommandUIExtension>
  <CommandUIDefinitions>
    <CommandUIDefinition Location="Ribbon.Documents.Groups._children">
      <Group Id="Ribbon.Documents.ApplyDocumentPrefix" ... >
        ...
      </Group>
    </CommandUIDefinition>
    <CommandUIDefinition Location="Ribbon.Documents.Scaling._children">
      <MaxSize Id="Ribbon.Documents.Scaling.ApplyDocumentPrefix.MaxSize"
               GroupId="Ribbon.Documents.ApplyDocumentPrefix"
               Size="MsdnVertical"
               Sequence="15" />
    </CommandUIDefinition>
    <CommandUIDefinition Location="Ribbon.Templates._children">
      <GroupTemplate Id="Ribbon.Templates.MsdnTemplate">
        ...
      </GroupTemplate>
    </CommandUIDefinition>
  </CommandUIDefinitions>
  <CommandUIHandlers />
</CommandUIExtension>

圖 十二、13 和 14 演示如何僅經過將 <MaxSize Size="" /> 屬性更改成不一樣的佈局選項來更改組的呈現。



圖 12. 使用 MsdnHorizontal 佈局


 



圖 13. 使用 MsdnVertical 佈局


 



圖 14. 使用 MsdnVerticalTextOnly 佈局

步驟 1.3:向功能區組添加控件

接下來,向元素清單文件添加如下標記,以向組中添加幾個按鈕。

XML
複製
<CommandUIExtension>
  <CommandUIDefinitions>
    <CommandUIDefinition Location="Ribbon.Documents.Groups._children">
      <Group Id="Ribbon.Documents.ApplyDocumentPrefix" ... > 
        <Controls Id="Ribbon.Documents.ApplyDocumentPrefix.Controls">
          <Button Id="Ribbon.Documents.ApplyDocumentPrefix.CustomHelpButton"
                  LabelText="Apply Document Prefix Help"
                  TemplateAlias="o1"
                  Sequence="15"
                  Image16by16="/_layouts/Images/ApplyDocumentPrefixRibbon/16x16Placeholder.png"
                  Image32by32="/_layouts/Images/ApplyDocumentPrefixRibbon/32x32Placeholder.png"
                  Command="ApplyDocumentPrefix.OnGetHelpApplyDocPrefix" />
          <Button Id="Ribbon.Documents.ApplyDocumentPrefix.CustomApplyPrefixButton"
                  LabelText="Apply Prefix w/ CommandUI Handler"
                  TemplateAlias="o2"
                  Sequence="17"
                  Image16by16="/_layouts/Images/ApplyDocumentPrefixRibbon/16x16Placeholder.png"
                  Image32by32="/_layouts/Images/ApplyDocumentPrefixRibbon/32x32Placeholder.png"
                  Command="ApplyDocumentPrefix.OnApplyDocPrefixUIHandler" />
          <Button Id="Ribbon.Documents.ApplyDocumentPrefix.CustomPageComponentButton"
                  LabelText="Apply Prefix w/ Page Component"
                  TemplateAlias="o3"
                  Sequence="19"
                  Image16by16="/_layouts/Images/ApplyDocumentPrefixRibbon/16x16Placeholder.png"
                  Image32by32="/_layouts/Images/ApplyDocumentPrefixRibbon/32x32Placeholder.png"
                  Command="ApplyDocumentPrefix.OnApplyDocPrefixPageComponent" />
        </Controls>
      </Group>
    </CommandUIDefinition>
  </CommandUIDefinitions>
  <CommandUIHandlers />
</CommandUIExtension>

請注意,每一個按鈕都會鏈接到其本身的命令。在完成功能區自定義項的可見部分後,緊接着是建立用於處理按鈕的可用時間以及按鈕被單擊時執行的操做的命令。經過使用命令 UI 處理程序或頁面組件可完成此操做。後面的兩個步驟將演示如何實現這兩點。

步驟 2:建立服務器功能區命令 UI 處理程序

在包含功能區可見自定義項的同一元素清單文件中定義命令 UI 處理程序。添加如下標記以建立首個命令 UI 處理程序。

XML
複製
<CommandUIHandlers>
  <CommandUIHandler Command="ApplyDocumentPrefix.OnGetHelpApplyDocPrefix"
      CommandAction="javascript:
        var dialogOptions = {
          url: '/_layouts/ApplyDocumentPrefixRibbon/DocPrefixHelp.aspx',
          title: 'Apply Document Prefix Help',
          allowMaximize: true,
          showClose: true,
          width:500,
          height:400
        };
        SP.UI.ModalDialog.showModalDialog(dialogOptions); " />
</CommandUIHandlers>

經過使用 Command 屬性將此命令鏈接到第一個按鈕。CommandAction 屬性會執行一些 ECMAScript,這將使用指向一個稍後將建立的自定義應用程序頁的 SharePoint 2010 對話框框架來打開一個對話框。

添加將與第二個按鈕關聯的另外一個命令 UI 處理程序。此處理程序執行了大量工做,如如下標記所示。

XML
複製
<CommandUIHandlers>
  <CommandUIHandler Command="ApplyDocumentPrefix.OnGetHelpApplyDocPrefix" ... />
  <CommandUIHandler Command="ApplyDocumentPrefix.OnApplyDocPrefixUIHandler"
      CommandAction="javascript:
        function dialogCallback(dialogResult, returnValue){
          SP.UI.Notify.addNotification(returnValue);
          SP.UI.ModalDialog.RefreshPage(SP.UI.DialogResult.OK);
        }
      
        var selectedItems = SP.ListOperation.Selection.getSelectedItems();
        var selectedItemIds = '';
        var selectedItemIndex;
        for (selectedItemIndex in selectedItems){
          selectedItemIds += '|' + selectedItems[selectedItemIndex].id;
        }
       
        var dialogOptions = {
          url: '/_layouts/ApplyDocumentPrefixRibbon/DocPrefixPrompt.aspx?selectedItems='
          +selectedItemIds +'&amp;ListId=' +SP.ListOperation.Selection.getSelectedList(),
          title: 'Set Document Prefix',
          allowMaximize: false,
          showClose: false,
          width:500,
          height:400,
          dialogReturnValueCallback: dialogCallback
        };
        
        SP.UI.ModalDialog.showModalDialog(dialogOptions);"
      EnabledScript="javascript:
        function checkIsEnabled(){
          // Check items selected.
          var selectedItems = SP.ListOperation.Selection.getSelectedItems();
          var count = CountDictionary(selectedItems);
          return (count > 0);
        }; 
                      
        checkIsEnabled();"
    />
</CommandUIHandlers>

此處理程序更爲複雜一些。首先,它建立一個新的 ECMAScript 函數,此函數在關閉對話框時將用做回調。它在瀏覽器中顯示一個通知(從頁面右側滑入的用黃色顯示的消息),而後刷新頁面上的列表視圖 Web 部件。

而後,它建立一個在當前頁面上選定的文檔的分隔列表。最後,它建立一個新對話框,該對話框將打開一個新的應用程序頁並傳入選定項。當對話框關閉時,它將調用前面定義的 dialogCallback 方法。

它的另外一個重要部分是 EnabledScript 屬性。若是命令可用,則此屬性返回的布爾值爲 TRUE;若是命令不可用,則返回 FALSE。爲了肯定這一點,它將檢查是否已在頁面上選定其餘選項。若是未選定,則將禁用命令和此按鈕。

步驟 3:建立服務器功能區頁面組件

在功能區中具備一個使用在命令 UI 處理程序中定義的命令的按鈕以後,如今能夠建立頁面組件來處理其餘命令。經過將新的 ECMAScript 文件添加到 Visual Studio 項目(最好是添加到已映射到 {SharePoint Root}/TEMPLATE/LAYOUT/{ProjectName} 目錄的文件夾中)來實現這一點。這將確保供全部網站使用的前端 Web 服務器上只有一個庫實例。

步驟 3.1:聲明頁面組件對象

在將文件添加到項目後,將如下腳本添加到庫以聲明此庫將包含的 ECMAScript 對象,以及少許構造函數和初始化方法,它們將建立一個頁面組件實例並將該實例添加到客戶端功能區管理器。如下標記對此進行了演示。

複製
// Register the page component object.
Type.registerNamespace('ApplyDocumentPrefix');

// Helper methods to set up and initialize the page component.
ApplyDocumentPrefix.ApplyDocumentPrefixPageComponent = function ApplyDocumentPrefix_PageComponent() {
  ApplyDocumentPrefix.ApplyDocumentPrefixPageComponent.initializeBase(this);
}

ApplyDocumentPrefix.ApplyDocumentPrefixPageComponent.initialize = function () {
  ExecuteOrDelayUntilScriptLoaded(Function.createDelegate(null, 
  ApplyDocumentPrefix.ApplyDocumentPrefixPageComponent.initializePageComponent), 'SP.Ribbon.js');
}

ApplyDocumentPrefix.ApplyDocumentPrefixPageComponent.initializePageComponent = function () {
  var ribbonPageManager = SP.Ribbon.PageManager.get_instance();
  if (ribbonPageManager !== null) {
    ribbonPageManager.addPageComponent(ApplyDocumentPrefix.ApplyDocumentPrefixPageComponent.instance);
  }
}

步驟 3.2:建立頁面組件對象原型和 init 方法

如今,爲對象原型和核心 init 方法添加如下腳本。從其名稱能夠了解,此方法將經過建立幾個數組來初始化對象,這些數組會列出命令並將命令映射到對象內的特定函數。

複製
// Page component object.
ApplyDocumentPrefix.ApplyDocumentPrefixPageComponent.prototype = {

  init: function ApplyDocumentPrefix_PageComponento$init() {
    // Array of commands that can be handled that are associated with handler methods.
    this.handledCommands = new Object;
    this.handledCommands['ApplyDocumentPrefix.OnApplyDocPrefixPageComponent'] = 
    this.onApplyDocPrefixPageComponent;

    // Array of commands that can be handled that are associated with canHandler methods.
    this.canHandledCommands = new Object;
    this.canHandledCommands['ApplyDocumentPrefix.OnApplyDocPrefixPageComponent'] = 
    this.onApplyDocPrefixPageComponent_canExecute;

    // Array of commands.
    this.commandList = ['ApplyDocumentPrefix.OnApplyDocPrefixPageComponent'];
  },
  getId: function ApplyDocumentPrefixPageComponent_PageComponent$getId() {
    return "ApplyDocumentPrefixPageComponent";
  },  ...
}

請注意,在定義功能區自定義項的可見組件時,數組中命令的名稱與前面添加的 <Button Command="" /> 屬性的值匹配。

步驟 3.3:添加方法以告知功能區管理器此頁面組件處理的命令以及處理命令的方式和時間

接下來,添加四個方法,這四個方法告知客戶端功能區管理器哪些命令可用以及處理這些命令的方式和時間,如如下代碼所示。

複製
ApplyDocumentPrefix.ApplyDocumentPrefixPageComponent.prototype = {
  ...
  getFocusedCommands: function ApplyDocumentPrefixPageComponent_PageComponent$getFocusedCommands() {
    return [];
  },

  getGlobalCommands: function ApplyDocumentPrefixPageComponent_PageComponent$getGlobalCommands() {
    return this.commandList;
  },

  canHandleCommand: function 
  ApplyDocumentPrefixPageComponent_PageComponent$canHandleCommand(commandID) {
    var canHandle = this.handledCommands[commandID];
    if (canHandle)
      return this.canHandledCommands[commandID]();
    else
      return false;
  },

  handleCommand: function 
  ApplyDocumentPrefixPageComponent_PageComponent$handleCommand(commandID, 
  properties, sequence) {
    return this.handledCommands[commandID](commandID, properties, sequence);
  },
  ...
}

canHandleCommand 方法與命令 UI 處理程序的 EnabledScript 屬性的功能相同,這些屬性告知功能區管理器命令是否可用。在上一個代碼段中,該方法使用在對象的初始值設定項中建立的數組來調用對象中的特定方法。handleCommand 的功能與命令 UI 處理程序的 CommandAction 屬性的功能類似。它也使用一個數組以指向指定命令的另外一個方法。

步驟 3.4:添加特定命令方法

接下來是,添加已在對象的初始值設定項中定義且被調用的方法,以肯定命令什麼時候可用 (onApplyDocPrefixPageComponent_canExecute) 以及執行命令時發生的操做 (onApplyDocPrefixPageComponent)。

複製
ApplyDocumentPrefix.ApplyDocumentPrefixPageComponent.prototype = {
  ...
  onApplyDocPrefixPageComponent: function () {
    var selectedItems = SP.ListOperation.Selection.getSelectedItems();
    var selectedItemIds = '';
    var selectedItemIndex;
    for (selectedItemIndex in selectedItems) {
      selectedItemIds += '|' + selectedItems[selectedItemIndex].id;
    }

    var dialogOptions = {
      url: '/_layouts/ApplyDocumentPrefixRibbon/DocPrefixPrompt.aspx?selectedItems=' + 
      selectedItemIds + '&ListId=' + SP.ListOperation.Selection.getSelectedList(),
      title: 'Set Document Prefix',
      allowMaximize: false,
      showClose: false,
      width: 500,
      height: 400,
      dialogReturnValueCallback: PageComponentCallback
    };

    SP.UI.ModalDialog.showModalDialog(dialogOptions);
  },

  onApplyDocPrefixPageComponent_canExecute: function () {
    var selectedItems = SP.ListOperation.Selection.getSelectedItems();
    var count = CountDictionary(selectedItems);
    return (count > 0);
  }
  ...
}
function PageComponentCallback(dialogResult, returnValue) {
  SP.UI.Notify.addNotification(returnValue);
  SP.UI.ModalDialog.RefreshPage(SP.UI.DialogResult.OK);
}

步驟 3.5:添加最後對象註冊、初始化和通知腳本

完成頁面組件對象以後,最後的步驟是:在頁面上註冊該對象;建立該對象;通知客戶端功能區,正在等待此腳本完成該對象加載的任何操做已完成加載和初始化。這些步驟如如下代碼所示。

複製
ApplyDocumentPrefix.ApplyDocumentPrefixPageComponent.prototype = {
  ...
}
ApplyDocumentPrefix.ApplyDocumentPrefixPageComponent.registerClass
('ApplyDocumentPrefix.ApplyDocumentPrefixPageComponent', 
CUI.Page.PageComponent);
ApplyDocumentPrefix.ApplyDocumentPrefixPageComponent.instance = 
new ApplyDocumentPrefix.ApplyDocumentPrefixPageComponent();
ApplyDocumentPrefix.ApplyDocumentPrefixPageComponent.initialize();
SP.SOD.notifyScriptLoadedAndExecuteWaitingJobs("ApplyDocumentPrefix.UI.js");

此時,已建立頁面組件,而且如今可將該組件添加到頁面。

步驟 4:建立服務器功能區頁面組件加載程序

接下來,必須將頁面組件添加到頁面。在此示例中,自定義服務器控件用於執行此操做。向項目中添加一個新的 Empty Element SharePoint 項目項。使用 <Control /> 元素以註冊一個具備如下標記的新委託控件。

XML
複製
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Control Id="AdditionalPageHead"
           ControlClass="MSDN.SharePoint.Samples.ApplyDocumentPrefix.PageComponentScriptLoader"
           ControlAssembly="$SharePoint.Project.AssemblyFullName$" />
</Elements>

這會將服務器控件 PageComponentScriptLoader 添加到當前網站中全部頁面的 AdditionalPageHead 內容佔位符中(無論功能的範圍如何)。如今,向 SharePoint 項目項中添加一個新的代碼文件,並添加如下代碼以實現服務器控件。

複製
public class PageComponentScriptLoader : WebControl {
  protected override void OnPreRender(EventArgs e) {
    SPRibbon ribbon = SPRibbon.GetCurrent(this.Page);

    // Ensure ribbon exists and current list is a document library 
    // (otherwise, no need for extra ecmascript load).
    if (ribbon != null && SPContext.Current.List is SPDocumentLibrary) {
      // Load dependencies if not already on the page.
      ScriptLink.RegisterScriptAfterUI(this.Page, "SP.Ribbon.js", false, true);

      // Load page component.
.      ScriptLink.RegisterScriptAfterUI(this.Page, "ApplyDocumentPrefixRibbon/ApplyDocumentPrefix.UI.js", false, true);
    }

    base.OnPreRender(e);
  }
}

這將首先獲取對服務器功能區的引用。當用戶使用文檔庫時,它將首先驗證頁面上的從屬腳本,而後再註冊頁面組件。

此處的最後一個步驟是,將 <SafeControl /> 項添加到網站的 web.config 文件。雖然「空元素」SharePoint 項目項不自動添加 <SafeControl /> 項,但它爲咱們提供了執行此操做的方法。在 Visual Studio 2010 中的「解決方案資源管理器」中,選擇「空元素」。在「屬性」窗口中,單擊「[…]」生成器按鈕,如圖 15 所示。



圖 15. 使用 Visual Studio 2010 中的 SharePoint 開發工具手動添加安全控制項


在「安全控制項」對話框中,添加一個新項,而後驗證命名空間是否與先前建立的服務器控件的命名空間匹配。



圖 16.「安全控制項」對話框


 

步驟 5:建立自定義對話框

最後一個步驟是,建立由自定義功能區命令調用的且執行大部分工做的對話框。將一個新的「應用程序頁」SharePoint 項目項添加到 Visual Studio 項目。

步驟 5.1:實現對話框的可見部分 (.aspx)

在此示例中,對話框使用了幾個 SharePoint 管理表單用戶控件,所以須要一些引用,如如下代碼所示。

複製
<%@ Register TagPrefix="wssuc" TagName="InputFormSection" 
Src="~/_controltemplates/InputFormSection.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="InputFormControl" 
src="~/_controltemplates/InputFormControl.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="ButtonSection" 
Src="~/_controltemplates/ButtonSection.ascx" %>

PlaceHolderMain 內容佔位符中,添加如下標記以建立帶 ASP.NET DataList 控件的表單,該控件將顯示全部選定文檔的列表。

複製
<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
  <table border="0" cellspacing="0" cellpadding="0" width="100%">
    <tr>
      <td>
        <wssuc:InputFormSection runat="server" 
                                Title="Selected Documents" 
                                Description="The following documents have been selected 
                                to have the specified prefix added to their titles.">
          <Template_InputFormControls>
                        <tr>
                          <td>
                            <asp:DataList ID="SelectedDocumentsDataList" runat="server"
                            RepeatColumns="2" CellPadding="2" CellSpacing="5">
                  <ItemTemplate><li><%# DataBinder.Eval(Container.DataItem, 
                  "File.Name").ToString()%></li></ItemTemplate>
                </asp:DataList>
                          </td>
                        </tr>
                  </Template_InputFormControls>
        </wssuc:InputFormSection>

        <wssuc:InputFormSection runat="server" 
                                Title="Document Prefix" 
                                Description="Prefix to add to the selected document 
                                titles.">
          <Template_InputFormControls>
            <wssuc:InputFormControl LabelText="Prefix to add to the selected documents:"
            runat="server">
              <Template_control>
                <asp:TextBox ID="DocumentPrefixTextBox" runat="server" />
              </Template_control>
            </wssuc:InputFormControl>
                  </Template_InputFormControls>
        </wssuc:InputFormSection>

        <wssuc:ButtonSection runat="server" ShowStandardCancelButton="FALSE" 
        TopButtons="TRUE">
          <Template_Buttons>
            <asp:Button ID="SetPrefixButton" class="ms-ButtonHeightWidth" runat="server" 
            Text="Set Prefix" OnClick="OnClickSetPrefixButton" />
            <asp:Button ID="CancelButton" class="ms-ButtonHeightWidth" runat="server" 
            Text="Cancel" OnClientClick=
            "SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel,
            'Assignment of prefix cancelled.'); return false;" />
          </Template_Buttons>
        </wssuc:ButtonSection>
      </td>
    </tr>
  </table>
</asp:Content>

步驟 5.2:實現代碼隱藏中的業務邏輯 (.aspx.cs)

此應用程序頁的代碼隱藏很是簡單。它須要執行如下任務:

  • 獲取在 QueryString 上傳入的全部選定文檔的列表。

  • 獲取對包含在 QueryString 上傳入的文檔的列表的引用。

  • 顯示經過將選定文檔的集合綁定到 ASP.NET DataList 控件來選定的項。

  • 單擊時,將更新全部選定項的文件名。

  • 完成後,將一些 ECMAScript 寫入將關閉對話框的 PlaceHolderAdditionalPageHead 內容佔位符,這會將結果發送回調用頁面。

嚮應用程序頁的代碼隱藏文件中添加如下代碼。

複製
public partial class DocPrefixPrompt : LayoutsPageBase {
  List<SPListItem> _selectedListItems = new List<SPListItem>();

  protected override void OnLoad(EventArgs e) {
    // Get all the selected documents.
    SPList selectedDocumentLibrary = 
        SPContext.Current.Web.Lists[new Guid(
                  Request.QueryString["ListId"]
        )];
    string[] selectedItems = 
      Request.QueryString["selectedItems"].ToString().Split('|');

    for (int index = 1; index < selectedItems.Length; index++) {
      _selectedListItems.Add(
        selectedDocumentLibrary.GetItemById(
          int.Parse(selectedItems[index]))
      );
    }

    // Bind to the repeater.
    SelectedDocumentsDataList.DataSource = _selectedListItems;
    SelectedDocumentsDataList.DataBind();
  }

  protected void OnClickSetPrefixButton(object sender, EventArgs e) {
    foreach (SPListItem listItem in _selectedListItems) {
      listItem["Name"] = 
        DocumentPrefixTextBox.Text + " " + listItem.File.Name;
      listItem.Update();
    }

    CloseDialogOnSuccess();
  }
  private void CloseDialogOnSuccess() {
    ContentPlaceHolder pageHead = this.Master.FindControl("PlaceHolderAdditionalPageHead") as ContentPlaceHolder;
    if (pageHead != null)
      pageHead.Controls.Add(
        new LiteralControl("
<script language='javascript'>
ExecuteOrDelayUntilScriptLoaded(closeDialog,'sp.js');
function closeDialog(){
  SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, 'Prefix assigned to selected documents.');
}
</script>"));
  }
}

步驟 6:部署和測試自定義 Web 部件

在保存全部更改後,經過在 Visual Studio 2010 中按 F5,或經過在「調試」菜單上單擊「開始調試」來部署自定義 Web 部件。

在打開工做組網站的初始網頁時,單擊「共享文檔庫」。經過選擇功能區上的「文檔」選項卡可以使功能區自定義項可見,如圖 9 所示。在選定某個文檔後,將啓用自定義組中的全部按鈕,如圖 10 所示。單擊兩個「Apply Prefix […]」按鈕之一將觸發對話框,如圖 11 所示。

當用戶單擊「Set Prefix」按鈕時,該對話框將更新選定的文件名,而後關閉。以後,命令將發出一條代表已應用更改的通知消息,並刷新列表視圖 Web 部件。

自定義 SharePoint 2010 Server 功能區開發提示和技巧

在自定義 SharePoint 2010 服務器功能區時,開發人員能夠進行各類更改。提供了各類可用控件、可重用的模板以及可進行修改或添加操做的組和選項卡。幸運的是,大多數功能區是以聲明方式構造的,或(對於頁面組件)駐留在比已編譯代碼更易讀取的腳本文件中。這意味着,在安裝 SharePoint 後,開發人員將擁有大量可用的代碼示例。

技巧在於瞭解這些示例的查找位置和查找方式。可在全局網站定義的 {SharePoint Root}\TEMPLATE\GLOBAL\XML\CMDUI.XML 文件中找到基服務器功能區和全部功能區聲明。一般,能夠在各類功能中找到由 SharePoint Server 2010 企業內容管理等項進行的其餘更改。只需在全部 *.xml 文件中搜索 <CommandUIExtension> 元素,就將顯示包含功能區擴展的全部功能的列表。

如下各節針對自定義功能區的一些常見狀況,幫助開發人員找到正確的方向。

查找選項卡、組以及控件名稱和序列

建立新選項卡、將組添加到選項卡或修改現有控件是一項常見任務。第一個步驟是查找選項卡的 ID 或名稱。SharePoint 2010 SDK 包含全部選項卡及其位置的列表。有關詳細信息,請參閱默認服務器功能區自定義位置。因爲選項卡名稱的描述很清晰,所以很容易瞭解哪一個選項卡對應哪一個名稱。此頁還包含全部組及其控件的名稱的列表。僅缺乏序列和模板別名。

若要查找序列和模板別名,請打開 CMDUI.xml 文件並搜索相關選項卡、組或 SDK 中列出的控件 ID。這樣,您將得到可回答有關控件的任何問題的相關項。

始終獲取清除頁面請求:清除瀏覽器緩存

在自定義功能區時,開發人員確定會編寫 ECMAScript 並引用圖像。ECMAScript 和圖像及功能區自定義項的數量取決於應用程序的複雜度。

在重構 SharePoint 2010 UI 並開發功能區時,Microsoft 會側重於儘量地限制頁面的權重或頁面上所需的全部內容的組合大小。爲此,SharePoint 會主動在瀏覽器中緩存 CSS 文件和 ECMAScript 庫。這反過來爲用戶提供了更短的頁面加載時間,由於後續請求上請求的文件更少。

雖然這爲用戶帶來了好處,但同時也爲開發人員帶來了挑戰。因爲瀏覽器未下載最新的腳本或自定義項,所以沒法顯示在正在調試的會話間所作的更改。在部署解決方案後等待加載解決方案時的最佳作法是,使用 Internet Explorer 開發人員工具欄



圖 17. 清除 IE 緩存並強制下載全部文件


Internet Explorer 開發人員工具欄還提供了瀏覽腳本文件的方法。若要驗證瀏覽器是否下載了最新版本的自定義腳本文件,請使用「腳本」選項卡,並選擇已由頁面加載的腳本文件。若是未列出外部腳本文件,則不會將其添加到頁面。圖 18 演示了從上一個示例中選擇頁面組件外部腳本庫並查看其內容。



圖 18. 使用 IE 開發人員工具欄進行的腳本調試


 

結論

本文說明了構成 Microsoft SharePoint 2010 服務器功能區的核心組件。而後,向您演示如何建立使用不一樣的自定義技術的兩個示例功能區更改。另外,本文還提供有關什麼時候考慮不一樣的命令實現選項(命令 UI 處理程序或頁面組件)的指南,並提供了有關功能區自定義項開發的提示和技巧。

相關文章
相關標籤/搜索