SharePointCommunity
Die deutschsprachige Community für SharePoint, Microsoft 365, Teams, Yammer und mit Azure
SharePoint 2010 Ribbon anpassen und erweitern

Blogs

Fabian´s Blog [SharePoint MVP]

Syndication

Eine der wesentlichen neuen Funktionen in SharePoint Foundation 2010 ist die Integration des aus Office 2007 bekannten Ribbons. Die Ribbon-Technologie wurde durchgängig in die SharePoint-Benutzeroberfläche integriert und macht die Arbeit und Interaktion mit SharePoint-Funktionen zukünftig deutlich einfacher. Die Technologie der Ribbons kann auch für eigene Webparts oder benutzerdefinierte Anwendungen genutzt werden. In diesem Artikel möchte ich die Technologie der SharePoint Ribbons vorstellen und beschreiben, wie sich der Ribbon anpassen und um neue Elemente erweitern lässt.

Zunächst ein paar grundsätzliche Worte: Die Ribbon-Technologie basiert auf einem deklarativen Modell. Ribbons werden vollständig via XML beschrieben. Die XML-Definition des Standard-Ribbons befindet sich direkt auf dem SharePoint-Server im Verzeichnis C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\GLOBAL\XML\CMDUI.XML. Diese Datei beschreibt vollständig die Struktur des SharePoint Standard-Ribbons; wer sich in diese Thematik einarbeiten möchte, sollte unbedingt einen Blick auf diese XML-Datei werfen! Die Hierarchie der Ribbon-Elemente ist stets gleich: Ribbon > Tab > Group > Control. Innerhalb des Control-Elements können unterschiedliche Controls platziert werden; die bekanntesten seiner Vertreter sind der Button, eine Checkbox, ein Dropdown-Feld oder eine Textbox. Beachtet werden sollte, dass der Ribbon es nicht ermöglicht, benutzerdefinierte Steuerelemente einzubetten.

Eigene Ribbons werden mittels eines Element Manifests in die SharePoint-Oberfläche integriert. Das Manifest beginnt mit einem CustomAction-Attribut gefolgt von der Struktur der Ribbon-Elemente. Benutzerdefinierte Elemente können in einen beliebigen Bereich des Ribbons integriert werden; es ist ebenso möglich einen komplett neuen Tab in den Ribbon zu integrieren, wie auch ein einzelnen Button innerhalb einer definierte Gruppe. Die Ribbon-Technologie erlaubt auch die Einbettung von Programmcode. Der Code wird über das SharePoint ECMAScript (JavaScript; JScript) in den Ribbon integriert. Mittels des Client-Objektmodells kann der Ribbon mit Elementen der SharePoint-UI interagieren und so zum Beispiel Dialoge öffnen oder eine Nachricht in der Statusleiste ausgeben. Der Script Code kann direkt über das CommandAction-Attribut im Element Manifest definiert oder einer separaten Datei ausgelagert werden.

So viel zum theoretischen; gehen wir in die Praxis über! In meinem Beispiel möchte ich den allgemeinen Aufbau eines benutzerdefinierten Ribbons erläutern. Das Ergebnis sieht wie folgt aus:

image

Folgender XML-Block sorgt für die Erzeugung dieses Ribbon:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   3:   <CustomAction   
   4:     Id="FM.Ribbon.Tab"  
   5:     Location="CommandUI.Ribbon" 
   6:     RegistrationType="List" 
   7:     RegistrationId="101">
   8:     <CommandUIExtension>
   9:       <CommandUIDefinitions>        
  10:         <CommandUIDefinition Location="Ribbon.Tabs._children">
  11:           <Tab Id="FM.Ribbon.Tab" Title="My Tab" Sequence="101">
  12:             <Scaling Id="FM.Ribbon.Tab.Scaling">
  13:               <MaxSize Id="FM.Ribbon.Tab.Groups.GroupOne.MaxSize"                       
  14:                        GroupId="FM.Ribbon.Tab.Groups.GroupOne"                       
  15:                        Size="TwoLarge"/>
  16:               <MaxSize Id="FM.Ribbon.Tab.Groups.GroupOne.MaxSize"
  17:                        GroupId="FM.Ribbon.Tab.Groups.GroupTwo"
  18:                        Size="ThreeMedium"/>
  19:               <Scale Id="FM.Ribbon.Tab.Groups.GroupTwo.Scaling"                     
  20:                      GroupId="FM.Ribbon.Tab.Groups.GroupOne"                     
  21:                      Size="ThreeMedium"/>            
  22:             </Scaling>            
  23:             <Groups Id="FM.Ribbon.Tab.Groups">              
  24:               <Group                
  25:                 Id="FM.Ribbon.Tab.Groups.GroupOne"                                
  26:                 Title="Group"                
  27:                 Sequence="10"                
  28:                 Template="Ribbon.Templates.Large">
  29:                 <Controls Id="FM.Ribbon.Tab.Groups.GroupOne.Controls">                 
  30:                   <Button                    
  31:                     Id="FM.Ribbon.Tab.Groups.GroupOne.Buttons.ButtonOne"                    
  32:                     Command="CustomMessage"                    
  33:                     Sequence="10"
  34:                     Image16by16="/_layouts/images/SolutionActivate_16x16.png"
  35:                     Image32by32="/_layouts/images/SolutionActivate_32x32.png"
  36:                     LabelText="Button One"                    
  37:                     TemplateAlias="c1"/>
  38:                   <Button
  39:                     Id="FM.Ribbon.Tab.Groups.GroupOne.Buttons.ButtonTwo"
  40:                     Command="CustomMessage"
  41:                     Sequence="20"
  42:                     Image16by16="/_layouts/images/SolutionDeactivate_16x16.png"
  43:                     Image32by32="/_layouts/images/SolutionDeactivate_32x32.png"                    
  44:                     LabelText="Button Two"                    
  45:                     TemplateAlias="c2"/>                  
  46:                 </Controls>
  47:               </Group>
  48:               <Group
  49:                Id="FM.Ribbon.Tab.Groups.GroupTwo"
  50:                Title="Group"
  51:                Sequence="20"
  52:                Template="Ribbon.Templates.Medium">
  53:                 <Controls Id="FM.Ribbon.Tab.Groups.GroupTwo.Controls">
  54:                   <Button
  55:                     Id="FM.Ribbon.Tab.Groups.GroupTwo.Buttons.ButtonOne"
  56:                     Command="CustomMessage"
  57:                     Sequence="10"
  58:                     Image16by16="/_layouts/images/SolutionActivate_16x16.png"                    
  59:                     LabelText="Button One"
  60:                     TemplateAlias="c1"/>
  61:                   <Button
  62:                     Id="FM.Ribbon.Tab.Groups.GroupTwo.Buttons.ButtonTwo"
  63:                     Command="CustomMessage"
  64:                     Sequence="20"
  65:                     Image16by16="/_layouts/images/SolutionDeactivate_16x16.png"                         
  66:                     LabelText="Button Two"
  67:                     TemplateAlias="c2"/>
  68:                   <TextBox
  69:                     Id="FM.Ribbon.Tab.Groups.GroupTwo.TextBox"
  70:                     Sequence="30"
  71:                     Width="180"                    
  72:                     TemplateAlias="c3"/>                  
  73:                 </Controls>
  74:               </Group>
  75:             </Groups>
  76:           </Tab>
  77:         </CommandUIDefinition>
  78:         <CommandUIDefinition Location="Ribbon.Templates._children">
  79:           <GroupTemplate Id="Ribbon.Templates.Large">
  80:             <Layout Title="TwoLarge" LayoutTitle="TwoLarge">
  81:               <Section Alignment="Top" Type="OneRow">
  82:                 <Row>
  83:                   <ControlRef DisplayMode="Large" TemplateAlias="c1" />
  84:                 </Row>
  85:               </Section>
  86:               <Section Alignment="Top" Type="OneRow">
  87:                 <Row>
  88:                   <ControlRef DisplayMode="Large" TemplateAlias="c2" />
  89:                 </Row>
  90:               </Section>
  91:             </Layout>
  92:           </GroupTemplate>
  93:         </CommandUIDefinition>
  94:         <CommandUIDefinition Location="Ribbon.Templates._children">
  95:           <GroupTemplate Id="Ribbon.Templates.Medium">
  96:             <Layout Title="ThreeMedium" LayoutTitle="ThreeMedium">              
  97:               <Section Alignment="Top" Type="ThreeRow">
  98:                 <Row>
  99:                   <ControlRef DisplayMode="Medium" TemplateAlias="c1" />                  
 100:                 </Row>
 101:                 <Row>
 102:                   <ControlRef DisplayMode="Medium" TemplateAlias="c2" />
 103:                 </Row>
 104:                 <Row>
 105:                   <ControlRef DisplayMode="Medium" TemplateAlias="c3" />
 106:                 </Row>
 107:               </Section>              
 108:             </Layout>
 109:           </GroupTemplate>
 110:         </CommandUIDefinition>      
 111:       </CommandUIDefinitions>
 112:       <CommandUIHandlers>
 113:         <CommandUIHandler          
 114:           Command="CustomMessage"          
 115:           CommandAction="javascript:javascript:alert('Hello from the ribbon');" />       
 116:       </CommandUIHandlers>
 117:     </CommandUIExtension>
 118:   </CustomAction>  
 119: </Elements>

Jetzt werde ich mich Stück für Stück durch die einzelnen Elemente dieser XML-Struktur durcharbeiten:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   3:   <CustomAction   
   4:     Id="FM.Ribbon.Tab"  
   5:     Location="CommandUI.Ribbon" 
   6:     RegistrationType="List" 
   7:     RegistrationId="101">

CustomAction ist jeweils das Wurzelelement einer Ribbon-Erweiterung. Das Location-Attribut muss auf den Wert CommandUI.Ribbon gesetzt sein; damit bekommt das Element die Möglichkeit, benutzerdefinierte Erweiterungen im Ribbon zu registrieren. Die RegistrationID definiert den Bereich, für den die Erweiterung bereitgestellt wird. Als Bereiche können die BaseType IDs der SharePoint-Elemente angegeben werden; hier einige Beispiele: 100 = Generic List, 101 = Document library, 102 = Survey, 103 = Links, 104 = Announcements etc. Eine vollständige Liste der Template IDs liefert das SDK. In meinem Fall wird der neue Tab im Kontext einer Dokumentenbibliothek bereitgestellt. Der RegistrationType muss auf den Typ List gesetzt werden.

   1: <CommandUIDefinitions>        
   2:        <CommandUIDefinition Location="Ribbon.Tabs._children">
   3:          <Tab Id="FM.Ribbon.Tab" Title="My Tab" Sequence="101">
   4:            <Scaling Id="FM.Ribbon.Tab.Scaling">
   5:              <MaxSize Id="FM.Ribbon.Tab.Groups.GroupOne.MaxSize"                       
   6:                       GroupId="FM.Ribbon.Tab.Groups.GroupOne"                       
   7:                       Size="TwoLarge"/>
   8:              <MaxSize Id="FM.Ribbon.Tab.Groups.GroupOne.MaxSize"
   9:                       GroupId="FM.Ribbon.Tab.Groups.GroupTwo"
  10:                       Size="ThreeMedium"/>
  11:              <Scale Id="FM.Ribbon.Tab.Groups.GroupTwo.Scaling"                     
  12:                     GroupId="FM.Ribbon.Tab.Groups.GroupOne"                     
  13:                     Size="ThreeMedium"/>            
  14:            </Scaling>            
  15: 

CommandUIDefinitions ist das wichtigste Element der Ribbon-Erweiterung, weil hierüber der eigentliche Aufbau strukturiert wird. Über das Location-Attribut wird definiert, in welchem Bereich die jeweiligen Erweiterungen integriert werden sollen. Das Ribbon Framework stellt hierbei verschiedene Möglichkeiten bereit. Beispielweise kann ein einzelner Button in eine bestehende Gruppe (z. B. Ribbon.Documents.New.Controls._children) oder ein komplett neuer Tab (Ribbon.Tabs._children) in den obersten Bereich des Ribbon zu platzieren. Die _children-Signatur teilt dem Ribbon mit, das Element unterhalb dieses Bereichs zu integrieren. Eine Liste der möglichen Location-Elemente liefert das SharePoint SDK. Mittels des Sequence-Attributs wird die Position des Controls definiert. Die Tabs werden in 100er, die restlichen Elemente in 10er-Schritten positioniert; damit bleibt für benutzerdefinierte Tabs, Gruppen oder Controls reichlich Platz. Genauere Informationen zur Aufteilung der jeweiligen Controls kann der CMDUI.XML entnommen werden.

Das Tab-Element bildet das oberste Element des Ribbons. Innerhalb dieses Bereichs kann eine Sequenz von Gruppen und Controls aufgebaut werden.

Über das Skalings-Element wird festgelegt, wie sich die Controls bei Größenänderungen des Browsers verhalten. Die Skalierung erfolgt auf Ebene einer Gruppe. Pro Gruppe muss mindestens die MaxSize angegeben werden. Sie definiert die maximale Größe der Controls einer Gruppe. Über das Scale-Element wird die Größe bei reduzierter Skalierung definiert. Als Größenangabe wird das Layout eines GroupTemplates referenziert. Hierüber können acht verschiede Darstellungsmodi definiert werden. Dazu später mehr!

   1: <Groups Id="FM.Ribbon.Tab.Groups">              
   2:             <Group                
   3:               Id="FM.Ribbon.Tab.Groups.GroupOne"                                
   4:               Title="Group"                
   5:               Sequence="10"                
   6:               Template="Ribbon.Templates.Large">
   7:               <Controls Id="FM.Ribbon.Tab.Groups.GroupOne.Controls">                 
   8:                 <Button                    
   9:                   Id="FM.Ribbon.Tab.Groups.GroupOne.Buttons.ButtonOne"                    
  10:                   Command="CustomMessage"                    
  11:                   Sequence="10"
  12:                   Image16by16="/_layouts/images/SolutionActivate_16x16.png"
  13:                   Image32by32="/_layouts/images/SolutionActivate_32x32.png"
  14:                   LabelText="Button One"                    
  15:                   TemplateAlias="c1"/>
  16:                 <Button
  17:                   Id="FM.Ribbon.Tab.Groups.GroupOne.Buttons.ButtonTwo"
  18:                   Command="CustomMessage"
  19:                   Sequence="20"
  20:                   Image16by16="/_layouts/images/SolutionDeactivate_16x16.png"
  21:                   Image32by32="/_layouts/images/SolutionDeactivate_32x32.png"                    
  22:                   LabelText="Button Two"                    
  23:                   TemplateAlias="c2"/>                  
  24:               </Controls>
  25:             </Group>

Nach dem Skaling folgt das Groups-Element. Es schachtet eine Sequenz von Gruppen. Eine Gruppe (Group) hostet eine beliebige Anzahl an Controls. Über das Template-Attribut wird die Vorlage zur Darstellung der Elemente einer Gruppe referenziert. SharePoint liefert hierbei die Möglichkeit, ein Standard-Template zu verwenden (z. B. Ribbon.Templates.Flexible2 ) oder eine benutzerdefinierte Vorlage (GroupTemplate) zu spezifizieren. Das Flexible-Template kann in der CMDUI.CML nachgelesen werden. Weiterhin wird innerhalb des Group-Elements die Position über das Sequence-Attribut festgelegt. Anders als bei Tabs werden die Standardsequenzen in 10er-Schritten aufgebaut. Sollte die Gruppe in ein Standard-Tab integriert werden, sollte die Sequenz nicht durch 10 teilbar sein; bei benutzerdefinierten Gruppen kann die Sequenz frei gewählt wählen.

Innerhalb einer Gruppe kann eine beliebige Anzahl von Controls platziert werden. Das Ribbon Framework ermöglicht die Bereitstellung von Buttons, Checkboxen, Comboboxen, Drop Down-Feldern oder Textboxen. Eine Liste der von SharePoint unterstützen Controls liefert das SDK. Je nach Typ können dem Element unterschiedliche Eigenschaften mitgegeben werden. Bei Buttons beispielsweise das Icon, der Event Handler für das Command oder der Label-Text. Auch hier muss eine Sequenznummer angegeben werden. Über das TemplateAlias-Attribut wird ein Bereich des GroupTemplates zugeordnet. Hier besteht die Möglichkeit ein Standardalias (z. B. o1) oder den eines benutzerdefinierten Templates zu referenzieren.

   1: <CommandUIDefinition Location="Ribbon.Templates._children">
   2:           <GroupTemplate Id="Ribbon.Templates.Large">
   3:             <Layout Title="TwoLarge" LayoutTitle="TwoLarge">
   4:               <Section Alignment="Top" Type="OneRow">
   5:                 <Row>
   6:                   <ControlRef DisplayMode="Large" TemplateAlias="c1" />
   7:                 </Row>
   8:               </Section>
   9:               <Section Alignment="Top" Type="OneRow">
  10:                 <Row>
  11:                   <ControlRef DisplayMode="Large" TemplateAlias="c2" />
  12:                 </Row>
  13:               </Section>
  14:             </Layout>
  15:           </GroupTemplate>
  16:         </CommandUIDefinition>
  17: 

Über das GroupTemplate wird das HTML-Gerüst mittels Sektionen (Section) und Zeilen (Row) definiert. Pro Sektion werden die Ausrichtung (Top, Middle) und der Typ (Devider, OneRow, TwoRow, ThreeRow) definiert. Auf Ebene einer Zeile werden die Darstellungsart (z. B. Medium, Large, Text) sowie der Alias (TemplateAlias) definiert.

   1: <CommandUIHandlers>
   2:         <CommandUIHandler          
   3:           Command="CustomMessage"          
   4:           CommandAction="javascript: javascript:alert('Hello from the ribbon');" />       
   5:       </CommandUIHandlers>

Über das CommandUIHandlers-Element werden die Event Handler für die Buttons deklariert. Über das CommandAcition-Attribut kann das JavaScript hinterlegt werden, das beim jeweiligen Kommando ausgeführt werden soll. Hier besteht die Möglichkeit, einen kompletten Scriptblock oder die Referenz einer externen Methode zu hinterlegen.

Das Ribbon Customizing erinnert mich ein wenig an die Anfangszeit der Entwicklung von Office 2007-Ribbons. Bei so vielen manuellen Schritten bleibt nur zu hoffen, dass Microsoft oder die Community demnächst ein Ribbon Designer herausbringt.


Bereitgestellt 7 Mai 2010 9:05 von Fabian Moritz

Kommentare

Ardenda geschrieben re: SharePoint 2010 Ribbon anpassen und erweitern
on 30 Mai 2010 23:04

Hallo,

schöner Beitrag. Ich habe da grad ein Problem dass ich das Design nicht ändern kann. Wie ändert man das? Möchte eine andere Hintergrundfarbe. Leider ist alles in der CoreV4 hinterlegt und ich kann die ID nicht ändern.