Introduction to the SharePoint 2010 Server Ribbon
With the release of the 2007 Microsoft Office system,
Microsoft introduced a new user interface structure, known as the
ribbon, that replaced the previous application drop-down menus and
toolbars. The ribbon came about after much research suggested that
certain applications, such as Microsoft Word, contained so many commands
that users had trouble finding what they needed.
The premise behind the ribbon is that it provides a more results-driven interface. Users focus on what they are doing, and commands are presented only for those things they can do at a specific time. For example, there is no reason to provide commands to the user to interact with tables or images in a document when they are clearly typing text and do not have an image or table selected. However, by using the Insert tab, they can easily add a table or picture. Only when they have selected the table or picture do new command structures appear. When the table or picture loses focus, these commands disappear.
In the 2007 Microsoft Office system, the ribbon was implemented in Microsoft Word, Microsoft Excel, and Microsoft PowerPoint. Microsoft expanded on this and has added the ribbon to the all the Microsoft Office 2010 applications, including Microsoft OneNote 2010, Microsoft Access 2010, and Microsoft InfoPath 2010.
Like the Microsoft Office clients, SharePoint users were experiencing similar challenges in finding controls to complete their work. Commands existed in multiple places across the page, from the Site Actions menu to managing Web Parts, or to the Edit Control Block (ECB) menus in lists. Figure 1 shows all the menus that are available to users in a Windows SharePoint Services 3.0 site.
Figure 1. Menus and commands in Windows SharePoint Services 3.0
In Microsoft SharePoint 2010, Microsoft added the Server ribbon to SharePoint to address the same challenges users had with the many commands in the Microsoft Office clients. All commands and menu items have been pushed from the main workspace in SharePoint up into the ribbon, which remains pinned to the top of the browser window. Users of the 2007 Microsoft Office system or other applications that have implemented the ribbon will find the SharePoint ribbon very easy to adjust to because it is very similar to the Office client ribbons. It looks, works, and performs like the Office ribbon, and has the same controls as the Office ribbon. The only differences between the Office ribbon and the SharePoint Server ribbon are concerned with the technologies; for example, it is not easy to show different font renderings in the web (thin client) experience as it is in the desktop (thick client) experience.
The ribbon in SharePoint 2010 is built on a similar architecture to the Office client ribbon. Microsoft uses this architecture to implement the default ribbon in SharePoint 2010. This architecture also enables third-party developers to customize and extend the existing ribbon components that are included in SharePoint, and to create command structures.
This article explains the components of the SharePoint Server ribbon so that you can understand how the ribbon is constructed. Then, it explains and shows how developers can customize and extend the ribbon. The SharePoint Foundation 2010 General Reference has a section devoted to explaining the ribbon, and contains various customization walkthroughs. When customizing the ribbon, I recommend that you use this article in conjunction with the SharePoint Foundation 2010 General Reference, specifically the section Server Ribbon in SharePoint Foundation.
The premise behind the ribbon is that it provides a more results-driven interface. Users focus on what they are doing, and commands are presented only for those things they can do at a specific time. For example, there is no reason to provide commands to the user to interact with tables or images in a document when they are clearly typing text and do not have an image or table selected. However, by using the Insert tab, they can easily add a table or picture. Only when they have selected the table or picture do new command structures appear. When the table or picture loses focus, these commands disappear.
In the 2007 Microsoft Office system, the ribbon was implemented in Microsoft Word, Microsoft Excel, and Microsoft PowerPoint. Microsoft expanded on this and has added the ribbon to the all the Microsoft Office 2010 applications, including Microsoft OneNote 2010, Microsoft Access 2010, and Microsoft InfoPath 2010.
Like the Microsoft Office clients, SharePoint users were experiencing similar challenges in finding controls to complete their work. Commands existed in multiple places across the page, from the Site Actions menu to managing Web Parts, or to the Edit Control Block (ECB) menus in lists. Figure 1 shows all the menus that are available to users in a Windows SharePoint Services 3.0 site.
Figure 1. Menus and commands in Windows SharePoint Services 3.0
In Microsoft SharePoint 2010, Microsoft added the Server ribbon to SharePoint to address the same challenges users had with the many commands in the Microsoft Office clients. All commands and menu items have been pushed from the main workspace in SharePoint up into the ribbon, which remains pinned to the top of the browser window. Users of the 2007 Microsoft Office system or other applications that have implemented the ribbon will find the SharePoint ribbon very easy to adjust to because it is very similar to the Office client ribbons. It looks, works, and performs like the Office ribbon, and has the same controls as the Office ribbon. The only differences between the Office ribbon and the SharePoint Server ribbon are concerned with the technologies; for example, it is not easy to show different font renderings in the web (thin client) experience as it is in the desktop (thick client) experience.
The ribbon in SharePoint 2010 is built on a similar architecture to the Office client ribbon. Microsoft uses this architecture to implement the default ribbon in SharePoint 2010. This architecture also enables third-party developers to customize and extend the existing ribbon components that are included in SharePoint, and to create command structures.
This article explains the components of the SharePoint Server ribbon so that you can understand how the ribbon is constructed. Then, it explains and shows how developers can customize and extend the ribbon. The SharePoint Foundation 2010 General Reference has a section devoted to explaining the ribbon, and contains various customization walkthroughs. When customizing the ribbon, I recommend that you use this article in conjunction with the SharePoint Foundation 2010 General Reference, specifically the section Server Ribbon in SharePoint Foundation.
SharePoint 2010 Server Ribbon Architecture
The default ribbon is built by SharePoint and is based on a
single file that is part of the main installation. This file is part of
the global site definition that is found in the path
Although the CMDUI.xml file contains all the core Server ribbon components, this is not how additional customizations to the ribbon are implemented. SharePoint Features are used to implement additional changes to the ribbon. For example, Microsoft SharePoint Server 2010 includes many things that require ribbon modifications such as those related to Enterprise Content Management, Forms Services, and business intelligence. These changes are all implemented by using SharePoint Features. SharePoint developers can also customize the ribbon by using Features as described in Creating Custom SharePoint 2010 Server Ribbon Components, later in this article.
SharePoint 2010 has extended the Feature schema, specifically the <CustomAction /> element, to be the vehicle for all ribbon customizations. This is done by setting the Location attribute to CommandUI.Ribbon, and adding a <CommandUIExtension /> child element. The SharePoint 2010 SDK provides an overview of the Server Ribbon XML.
The following sections address the two core pieces of the ribbon: the components that make up the visual experience and the code that runs when one of the controls in the ribbon is clicked.
{SharePoint Root}\TEMPLATE\GLOBAL\XML\CMDUI.XML
. This file contains the definitions for the ribbon components in SharePoint Foundation 2010, such as the Browse, Page, List, Library, and Document tabs.Although the CMDUI.xml file contains all the core Server ribbon components, this is not how additional customizations to the ribbon are implemented. SharePoint Features are used to implement additional changes to the ribbon. For example, Microsoft SharePoint Server 2010 includes many things that require ribbon modifications such as those related to Enterprise Content Management, Forms Services, and business intelligence. These changes are all implemented by using SharePoint Features. SharePoint developers can also customize the ribbon by using Features as described in Creating Custom SharePoint 2010 Server Ribbon Components, later in this article.
SharePoint 2010 has extended the Feature schema, specifically the <CustomAction /> element, to be the vehicle for all ribbon customizations. This is done by setting the Location attribute to CommandUI.Ribbon, and adding a <CommandUIExtension /> child element. The SharePoint 2010 SDK provides an overview of the Server Ribbon XML.
The following sections address the two core pieces of the ribbon: the components that make up the visual experience and the code that runs when one of the controls in the ribbon is clicked.
SharePoint 2010 Server Ribbon Components
The SharePoint 2010 Server ribbon has various components, as shown in Figure 2.
Figure 2. SharePoint 2010 Server ribbon components
The callout numbers in the figure point to the following specific components:
Figure 2. SharePoint 2010 Server ribbon components
- Tab
- Group
- Control
- Contextual tab group
Tabs on the SharePoint 2010 Server Ribbon
Tabs are the root of the Server ribbon. They contain one
or more groups, and contain similar functions. For example, in Figure 2,
the Page tab that is currently selected contains functions that pertain to working with the current page.
Contextual Tab Groups on the SharePoint 2010 Server Ribbon
Contextual tab groups are used to provide functions that
are not global to the current context, such as the page. They appear
only when certain circumstances have been met and contain one or more
tabs.
For example, the ribbon in Figure 2 shows the Library Tools contextual tab group, which appears only when inside a document library or, as in this case, when the List View Web Part on the current page that is associated with a document library is selected.
Contextual tab groups hide functionality and menu choices from the user when they are not available, and appear when applicable. Other examples of contextual tab groups include the Editing Tools contextual tab group that appears when editing a wiki page, or the Picture Tools contextual tab group that appears when a picture is selected in edit mode.
For example, the ribbon in Figure 2 shows the Library Tools contextual tab group, which appears only when inside a document library or, as in this case, when the List View Web Part on the current page that is associated with a document library is selected.
Contextual tab groups hide functionality and menu choices from the user when they are not available, and appear when applicable. Other examples of contextual tab groups include the Editing Tools contextual tab group that appears when editing a wiki page, or the Picture Tools contextual tab group that appears when a picture is selected in edit mode.
Groups on the SharePoint 2010 Server Ribbon
Every tab in the ribbon contains a series of one or more
groups. Groups are used to associate controls with similar
functionality. Each group is associated with a template that defines the
layout of the group and how the group should appear based on the scale
of the ribbon. The scale of the ribbon refers to situations where there
are too many controls to show in the ribbon, for example, when the
browser is not in a full-screen maximized state and is in a windowed
state.
Group Templates on the SharePoint 2010 Server Ribbon
Group templates are used to define the different layout
options for the controls within a group. Microsoft includes 29 group
templates in the CMDUI.xml file (to locate them, search for the element <RibbonTemplates /> at the end of this file).
Controls on the SharePoint 2010 Server Ribbon
The ribbon would not be complete if users did not have
anything to select or click. Controls are the items that live inside the
ribbon that users can interact with. Controls reside within groups.
These include things such as buttons, toggle buttons, check boxes, text
boxes and many other controls. For a complete list of all the available
controls, see Architecture of the Server Ribbon.
Each control definition contains a Command attribute that tells the ribbon infrastructure what to do when it is clicked or selected.
Each control definition contains a Command attribute that tells the ribbon infrastructure what to do when it is clicked or selected.
Server Ribbon Commands in SharePoint 2010
The Server ribbon handles click or selection actions by the
user with commands. Those who are familiar with how the commanding
infrastructure works in Windows Presentation Foundation or Microsoft
Silverlight 4 will find near parity with the Server ribbon commanding
infrastructure. Each command is named. This name is referenced in a
control. At the core, commands contain two very important details:
Commands in the Server ribbon are written by using ECMAScript (JavaScript, JScript). There are two ways that you can implement commands:
- Whether the current command is available For example, the Delete command is available only in a document library or if documents are selected.
- What code should be run For example, the Delete command may use the SharePoint 2010 client-side object model to delete the item from the list, display a notification that the document was deleted, and refresh the List View Web Part on the page.
Commands in the Server ribbon are written by using ECMAScript (JavaScript, JScript). There are two ways that you can implement commands:
- Through command UI handlers
- Through page components
Implementing Server Ribbon Commands Using Command UI Handlers
Command UI handlers are implemented with a
mix of declarative markup and ECMAScript. They are defined in the same
Feature element manifest in which ribbon customizations are defined (by
using the <CommandUIExtension /> element) with a <CommandUIHandler /> element. This element contains the following three attributes:
Command UI handlers are generally easier to write and manage for most developers. Because they are defined declaratively, the ribbon framework handles adding the script to any page where the command is needed by a referencing control.
Disadvantages of Using Command UI Handlers
One of the disadvantages of command UI handlers is that they can become hard to manage, troubleshoot, and debug when they contain a significant amount of custom ECMAScript. Also, because they are added to every page as inline script blocks, they cannot be cached by the browser and must be downloaded each time, adding to the overall page weight.
- Command The name of the command as it will be referenced from a control.
- CommandAction The ECMAScript that is executed when the command is fired.
- EnabledScript The ECMAScript that is called by the Server ribbon command infrastructure to determine whether the command is available. This script should return a Boolean value, TRUE if the command is available, or FALSE if it is not available. If the command is not available, the ribbon infrastructure applies a gray mask to the command in the ribbon and does not call the command when the user selects it.
Command UI handlers are generally easier to write and manage for most developers. Because they are defined declaratively, the ribbon framework handles adding the script to any page where the command is needed by a referencing control.
Disadvantages of Using Command UI Handlers
One of the disadvantages of command UI handlers is that they can become hard to manage, troubleshoot, and debug when they contain a significant amount of custom ECMAScript. Also, because they are added to every page as inline script blocks, they cannot be cached by the browser and must be downloaded each time, adding to the overall page weight.
Implementing Server Ribbon Commands Using Page Components
An alternative to using command UI handlers is to use a page component.
A page component is an ECMAScript object that is defined in an external
script library (.js) file. The object implements a few properties and
methods that tell the Server ribbon command infrastructure how to
initialize it, what commands it can handle, and whether a specific
command is available, and can also respond when the page component
receives focus or loses focus.
This script file must be added to the same page where the ribbon customizations appear. This can be done in various ways. One way would be to use the new <CustomAction ScriptSrc="" /> capability in SharePoint 2010 to add the library to all pages in a site, site collection, web application, or farm, depending on the Feature's scope. Another approach is to add the script from managed code within a custom application or site page (.aspx), custom user control (.ascx), or custom server control. The following code example would add the page component file to the page from within a Web Part.
Advantages of Using Page Components
Because all the ECMAScript lives in an external script library, it is much easier to manage, troubleshoot, and debug a page component instead of a command UI handler (the Microsoft Visual Studio 2010 script debugger can set breakpoints and attach to the library). In addition, because it is an external library, browsers can cache the library without having to request it each time it is referenced on the page.
Page components also enable greater control over commands because they can enable or disable the page component from receiving or losing focus and handle events in each of these cases.
In addition, because they are external libraries, one page component can handle commands for multiple controls and so can be reused across various ribbon customizations.
Disadvantages of Using Page Components
One disadvantage of using page components, compared to using command UI handlers, is that page components require a considerable amount of script. This is primarily because developers are building, registering, and initializing a script object on the page. In addition, developers who are not familiar with object-oriented ECMAScript techniques can find this a bit challenging.
Another disadvantage of using page components is that they must be added to the page somehow, as this is not handled by the ribbon command infrastructure.
This script file must be added to the same page where the ribbon customizations appear. This can be done in various ways. One way would be to use the new <CustomAction ScriptSrc="" /> capability in SharePoint 2010 to add the library to all pages in a site, site collection, web application, or farm, depending on the Feature's scope. Another approach is to add the script from managed code within a custom application or site page (.aspx), custom user control (.ascx), or custom server control. The following code example would add the page component file to the page from within a Web Part.
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); } }
Because all the ECMAScript lives in an external script library, it is much easier to manage, troubleshoot, and debug a page component instead of a command UI handler (the Microsoft Visual Studio 2010 script debugger can set breakpoints and attach to the library). In addition, because it is an external library, browsers can cache the library without having to request it each time it is referenced on the page.
Page components also enable greater control over commands because they can enable or disable the page component from receiving or losing focus and handle events in each of these cases.
In addition, because they are external libraries, one page component can handle commands for multiple controls and so can be reused across various ribbon customizations.
Disadvantages of Using Page Components
One disadvantage of using page components, compared to using command UI handlers, is that page components require a considerable amount of script. This is primarily because developers are building, registering, and initializing a script object on the page. In addition, developers who are not familiar with object-oriented ECMAScript techniques can find this a bit challenging.
Another disadvantage of using page components is that they must be added to the page somehow, as this is not handled by the ribbon command infrastructure.
Customizing the SharePoint 2010 Server Ribbon
Developers are presented with two options when they want to
customize the SharePoint Server ribbon. Customizations can either be
applied declaratively or programmatically. The declarative approach, as
described previously in this article, is done by using Features;
specifically the <CustomAction /> element with the <CommandUIExtensions /> child element.
The programmatic approach involves adding the declarative constructs, as strings, to the Server ribbon objects. The remainder of this article focuses on the declarative approach because these techniques can be applied to the programmatic approach also. The SharePoint 2010 SDK contains a walkthrough about customizing the ribbon programmatically: Walkthrough: Create a Custom Web Part with a Contextual Tab.
The programmatic approach involves adding the declarative constructs, as strings, to the Server ribbon objects. The remainder of this article focuses on the declarative approach because these techniques can be applied to the programmatic approach also. The SharePoint 2010 SDK contains a walkthrough about customizing the ribbon programmatically: Walkthrough: Create a Custom Web Part with a Contextual Tab.
Customizing the Built-in SharePoint 2010 Server Ribbon Components
Developers can customize the ribbon in three ways:
Modifying and removing components such as tabs, groups, and controls are done very much the same way with the same schema elements. You modify an element by duplicating its ID and simply replacing its contents, very similar to the way that content placeholders work in Microsoft ASP.NET 2.0 master pages. Removing is the same as modifying, except that the container is left empty. For more information, see Declarative Customization of the Server Ribbon.
- Add components to the ribbon (tabs, contextual tab groups, groups, and controls).
- Modify existing components in the ribbon.
- Remove existing components from the ribbon.
Modifying and removing components such as tabs, groups, and controls are done very much the same way with the same schema elements. You modify an element by duplicating its ID and simply replacing its contents, very similar to the way that content placeholders work in Microsoft ASP.NET 2.0 master pages. Removing is the same as modifying, except that the container is left empty. For more information, see Declarative Customization of the Server Ribbon.
Creating Custom SharePoint 2010 Server Ribbon Components
The following two sections walk through how to customize the
SharePoint 2010 Server ribbon. Both walkthroughs use various techniques,
and each component is explained in detail. For the sample code for both
walkthroughs, see MSDN Sample - Customizing and Extending the SharePoint 2010 Server Ribbon. This sample code requires only a SharePoint Foundation 2010 site collection.
The first sample, WebPartRibbonContextualTab, shown in Figure 3, demonstrates how to create a custom Web Part that uses the following ribbon customizations:
Figure 3. Web Part with contextual tab group
The second sample, ApplyDocumentPrefixRibbon, shown in Figure 4, demonstrates how to implement the following customizations and techniques:
Figure 4. Custom group with page component
The first sample, WebPartRibbonContextualTab, shown in Figure 3, demonstrates how to create a custom Web Part that uses the following ribbon customizations:
- Contextual tab group
- Custom tab
- Custom group
- Command UI handlers
- Activating the contextual tab group only when the Web Part is on the page
- Triggering and handling a server-side postback when a button is clicked on the ribbon.
Figure 3. Web Part with contextual tab group
- A custom group in an existing ribbon tab.
- A custom group template with different layout options.
-
Two custom commands that perform identical actions, except
that one is implemented with a command UI handler and the other
implements a custom page component:
- The commands are disabled unless one or more documents in the library are selected.
- When clicked, the commands open a dialog box, pass the selected documents, and do some work based on user input.
- When the dialog box's work is complete, the dialog box closes, and the command displays a notification message and refreshes the List View Web Part instead of the whole page.
- A custom server control that conditionally loads the page component.
Figure 4. Custom group with page component
Some markup from the sample code has been omitted for readability. For the complete code reference, see MSDN Sample - Customizing and Extending the SharePoint 2010 Server Ribbon. |
How To: Create a Web Part–Enabled Contextual Tab and Leverage to Postbacks
In this sample, when the Web Part is added to the page the
contextual tab appears as shown earlier in Figure 3. This tab contains
two groups that provide a few buttons. The buttons in the first group do
not do anything but do show how to use one of the default templates.
However, the Write to Web Part via PostBack button
issues a postback. The Web Part contains code that checks whether the
button issued the postback, and if so, adds some text to the Web Part's
contents.
Step 1: Create the Web Part
The first step is to create the Web Part. Using the new
SharePoint development tools in Microsoft Visual Studio 2010, create a
SharePoint project and add a Web Part SharePoint project item to the
project. The CreateChildControls method does two
things: writes some text to the Web Part, and calls a method to handle
the case when a specific postback event is fired, as shown in the
following code.
Next, create the method that handles the postback event.
If it is a specific postback event, it writes some additional text to
the Web Part's contents, as shown in the following code.
The last step is to implement the code that will add the custom contextual tab to the page. This is done from the OnPreRender
phase of the Web Part's life cycle. It must get a reference to the
Server ribbon and ensures the script dependencies are already loaded on
the page. Finally, to show the contextual tab, it then makes the tab
with an ID of Ribbon.PropertyChangerTab available, and tells the ribbon to make the contextual tab with an ID of Ribbon.WebPartContextualTabGroup available when the page loads, as shown in the following code.
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(); } }
private void HandleRibbonPostback() { if (this.Page.Request["__EVENTTARGET"] == POSTBACK_EVENT) { this.Controls.Add( new LiteralControl( "<p>Responding to postback event from ribbon.</p>" ) ); } }
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); } }
Step 2: Create Server Ribbon Component Customizations
With the Web Part created, the next step is to create the
Server ribbon component customizations. To do this, you create a
contextual tab group, a tab with two groups, and a few controls.
The SharePoint development tools in Microsoft Visual Studio 2010 do not contain a SharePoint project item template for customizing the ribbon. However, the generic SharePoint project item Empty Element will work to contain the ribbon customizations, so add a new one to the project.
The SharePoint development tools in Microsoft Visual Studio 2010 do not contain a SharePoint project item template for customizing the ribbon. However, the generic SharePoint project item Empty Element will work to contain the ribbon customizations, so add a new one to the project.
Step 2.1: Add the Core Ribbon Markup to the Element
Add the following markup to the element.xml file in the new Element SharePoint project item for the project.
This will tell SharePoint the following:
<?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>
-
The element manifest contains ribbon customizations that apply to the ribbon everywhere (
<CustomAction Location="CommandUI.Ribbon" />
). There are five options for the Location attribute. The others enable developers to specify that the customizations should appear when the List View Web Part is present or on the display, new, or edit forms for an item. In addition, RegistrationType and RegistrationId enable developers to more granularly target where the customizations appear. For example, they could be targeted to a specific content type. All options are listed in Server Ribbon XML. - The basic structure for a ribbon customization is also included.
Step 2.2: Add a New Contextual Tab Group
Next, add the following markup that will create the contextual tab group.
The <CommandUIDefinition> Location attribute tells the ribbon to add the following contents, which are one or more <ContextualGroup /> elements, to the contextual tabs in the ribbon.
The <ContextualGroup /> element defines the new group. It has an Id attribute that matches the name of the contextual group that the Web Part's code told the ribbon to make visible initially when the page loaded.
The Sequence attribute tells SharePoint the order where this contextual group should exist when other contextual groups are present. The SharePoint contextual groups are given sequences that increment by 100, starting with 100, which is the Editing Tools contextual group. Therefore, our contextual group may show up first or second if the Editing Tools group is present. For information about how to find the names and sequences for other contextual groups, see the Custom SharePoint 2010 Server Ribbon Development Tips and Tricks section, later in this article.
The Command attribute associates this group with a command name. In some cases, it may make sense to have script run when this tab group is selected. However, in this case the command (implemented later) is used to tell the ribbon when to activate the contextual group. If this were not implemented, when a user clicked on anything it would trigger the ribbon to hide the custom group.
<?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>
The <ContextualGroup /> element defines the new group. It has an Id attribute that matches the name of the contextual group that the Web Part's code told the ribbon to make visible initially when the page loaded.
The Sequence attribute tells SharePoint the order where this contextual group should exist when other contextual groups are present. The SharePoint contextual groups are given sequences that increment by 100, starting with 100, which is the Editing Tools contextual group. Therefore, our contextual group may show up first or second if the Editing Tools group is present. For information about how to find the names and sequences for other contextual groups, see the Custom SharePoint 2010 Server Ribbon Development Tips and Tricks section, later in this article.
The Command attribute associates this group with a command name. In some cases, it may make sense to have script run when this tab group is selected. However, in this case the command (implemented later) is used to tell the ribbon when to activate the contextual group. If this were not implemented, when a user clicked on anything it would trigger the ribbon to hide the custom group.
Step 2.3: Add a Tab to the Contextual Tab Group
With the contextual tab group created, add the
following markup to add a new tab and define the maximum size layout
group template.
There are two things to notice in this snippet around the <MaxSize /> element. It associates the group defined later (via the GroupId attribute) with the layout option LargeLarge (via the Size attribute) that is defined in the template.
<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>
Step 2.4: Add Groups to the Tab
Now add the groups to the new tab by adding the following markup.
Although there are two groups in this sample, only the second one is shown in this code listing. Notice the groups have Id attributes that match the <MaxSize GroupId="" /> elements that were previously added.
Also notice that the groups are using a template named Ribbon.Templates.Flexible2. This template is included in the built-in CMDUI.xml ribbon declaration. When defining custom groups in ribbon customization Features, Microsoft recommends that developers create their own group template instead of using one of the provided group templates. The reason for this is that SharePoint does not load the entire ribbon for every page request; only the parts of the ribbon that are needed for the current context are loaded. This includes the group templates. Therefore, if developers rely on the built-in group templates, there is a chance the template will not be loaded for the current page and their ribbon customizations will not appear.
In the case of this sample customization, because this is part of a Web Part and a Web Part must be on a Web Parts page, an assumption is being made that this template will be loaded because it is part of the Page tab, which is on every Web Parts page.
For information about how to find the names of other templates, see Custom SharePoint 2010 Server Ribbon Development Tips and Tricks later in this article.
<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>
Also notice that the groups are using a template named Ribbon.Templates.Flexible2. This template is included in the built-in CMDUI.xml ribbon declaration. When defining custom groups in ribbon customization Features, Microsoft recommends that developers create their own group template instead of using one of the provided group templates. The reason for this is that SharePoint does not load the entire ribbon for every page request; only the parts of the ribbon that are needed for the current context are loaded. This includes the group templates. Therefore, if developers rely on the built-in group templates, there is a chance the template will not be loaded for the current page and their ribbon customizations will not appear.
In the case of this sample customization, because this is part of a Web Part and a Web Part must be on a Web Parts page, an assumption is being made that this template will be loaded because it is part of the Page tab, which is on every Web Parts page.
For information about how to find the names of other templates, see Custom SharePoint 2010 Server Ribbon Development Tips and Tricks later in this article.
Step 2.5: Add Controls to the Group
The last step in defining the visual part of the ribbon
customization is to add controls to the groups. Add the following
markup to the second group (refer to MSDN Sample - Customizing and Extending the SharePoint 2010 Server Ribbon for adding buttons to the first group).
This markup will add a new button control to the group with a label of Write to Web Part. When this button is clicked, it will trigger the Command="". The TemplateAlias
attribute tells the Server ribbon in what position in the defined group
template to place the button. Finally, the two image attributes are
used by the layouts to show the ribbon icons in different states. These
images can point to any image on the server. In this case, they are
pointing to images that were added to the project.
<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>
Step 3: Create Server Ribbon Commands
The last step is to define the two commands that were
referenced in the ribbon components. Add the following markup to the
element manifest.
The first <CommandUIHandler /> has
a command that is associated with the contextual tab group. As
previously discussed, this command does not do anything except to tell
the Server ribbon when it should be active. To keep it from disappearing
from the ribbon, its EnabledScript attribute will always return TRUE.
Therefore, if the contextual tab group is on the page, which it is when
the Web Part is on the page because the Web Part handles its
activation, it will never disappear.
The second <CommandUIHandler /> is associated with the button control. When it is clicked it fires a postback with an event named RibbonizedWebPartPostBack. Recall previously the code from the Web Part is listening for that event name and adds text to the Web Part when it sees it.
<?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>
The second <CommandUIHandler /> is associated with the button control. When it is clicked it fires a postback with an event named RibbonizedWebPartPostBack. Recall previously the code from the Web Part is listening for that event name and adds text to the Web Part when it sees it.
Step 4: Deploy and Test
After saving all changes, deploy the custom Web Part by pressing F5 in Visual Studio 2010 or by clicking Start Debugging on the Debug menu.
When the initial page loads, notice that the contextual tab is not present, as shown in Figure 5.
Figure 5. Home page of debugging site without contextual tab group
Now, put the page into edit mode by selecting the Page tab and then clicking Edit.
Insert the Web Part on the page in the default location. When the page
reloads, notice the contextual tab and the Web Part are visible, as
shown in Figure 6.
Figure 6. Contextual tab and Web Part are visible
Test the postback by selecting the Tools
tab in the custom contextual tab group, and then clicking the
appropriate button. The page should refresh and have additional text in
the Web Part, as shown in Figure 7.
Figure 7. Web Part responding to postback from ribbon
Also notice that the contextual tab group is appearing as
the second contextual tab group on the page. That is because the page
is still in edit mode and the sequence was set to 150, which is greater
than the Editing Tools sequence. After the page is taken out of edit
mode, the custom contextual group should appear in the first position.
When the initial page loads, notice that the contextual tab is not present, as shown in Figure 5.
Figure 5. Home page of debugging site without contextual tab group
Figure 6. Contextual tab and Web Part are visible
Figure 7. Web Part responding to postback from ribbon
Walkthrough: Add Buttons to the Document Tab and Conditionally Enable Them
The sample for this walkthrough shows how to add a new
group with buttons to an existing ribbon. When the project is deployed,
it registers a new group in the Documents tab, which is part of the Library Tools
contextual tab group. This contextual tab group will appear only when
the user is interacting with documents or in a document library. Figure 8
shows the home page of a team site without the ribbon, but when the
Shared Documents Library is selected, as shown in Figure 9, the
contextual tab group appears with the customizations.
Figure 8. Team site home page without document library selected
Figure 9. Team site home page with document library selected
Initially two of the three buttons are not enabled. It is
not until one or more documents are selected that the commands
associated with the buttons are enabled, as shown in Figure 10.
Figure 10. Ribbon buttons enabled when a document is selected
The two latter buttons, Apply Prefix w/ CommandUI Handler and Apply Prefix w/ Page Component,
do the exact same thing when clicked. However, as their names indicate,
one uses the command UI handlers and the other uses a custom page
component. When clicked, they collect a list of all the selected
documents on the page and pass them to a new dialog box, as shown in
Figure 11. This dialog box enables the user to add a prefix to the name
of all selected documents.
Figure 11. Custom dialog box fired from ribbon customizations
When the Set Prefix button is clicked, the
dialog box updates the names of all documents and then closes.
Depending on whether the dialog box was closed by clicking the Set Prefix button or by clicking Cancel, the command issues a notification message and then refreshes the List View Web Part on the page, updating the list's contents.
Figure 8. Team site home page without document library selected
Figure 9. Team site home page with document library selected
Figure 10. Ribbon buttons enabled when a document is selected
Figure 11. Custom dialog box fired from ribbon customizations
Step 1: Create Server Ribbon Component Customizations
The first step is to create a new SharePoint empty
project by using the SharePoint development tools in Microsoft Visual
Studio 2010. When the project is created, add a new Empty Element project item to the project that will contain the ribbon customizations.
Step 1.1: Add the Core Ribbon Markup to the Element
Within the element manifest, add the following markup.
This will add a new group to the Document tab's groups collection named Document Naming Tools, as indicated by
In addition, the group will not use one of the existing group templates, but instead will use a custom group template.
<?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>
<CommandUIDefinition Location="Ribbon.Documents.Groups._children">
.
The group has a Sequence of 25. The groups in the built-in SharePoint
2010 Server ribbon are numbered in increments of 10, starting at 10.
This means that the custom group defined here will show up in the third
position. In addition, the group will not use one of the existing group templates, but instead will use a custom group template.
Step 1.2: Add Custom Group Template
Add the following markup to add a custom group to the ribbon.
This template, Ribbon.Templates.MsdnTemplate, contains three different layouts. Each <Layout /> has a Title attribute, which is referenced in the <MaxSize /> element or the <Scale /> element. This tells the ribbon which template to use for the layout. Each <Layout /> element has a <Section /> that defines how the group will be rendered by using the Type
attribute. This can be one of four options to render the group, using
one, two, or three rows, or by using a divider. For more information,
see Section Element.
The <Section /> contains one or more <Row /> elements that define each row in the layout. These <Row /> elements contain <ControlRef /> elements that serve as placeholders for controls. The DisplayMode attribute tells the ribbon how to render the control, by using just the text label, the large icon, the small icon, or one of the other choices that are defined in the schema of the ControlRef element. The TemplateAlias attribute is used to call out a specific control placement. When adding controls to the group, each control's TemplateAlias attribute will match one of these TemplateAlias attributes to specify exactly where to place the control.
Now add the following markup to tell the ribbon how to render the group by using one of the layouts in the defined template.
Figures 12, 13, and 14 show how just changing the <MaxSize Size="" /> attribute to the different layout options can change the rendering of the group.
Figure 12. Using the MsdnHorizontal layout
Figure 13. Using the MsdnVertical layout
Figure 14. Using the MsdnVerticalTextOnly layout
<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>
The <Section /> contains one or more <Row /> elements that define each row in the layout. These <Row /> elements contain <ControlRef /> elements that serve as placeholders for controls. The DisplayMode attribute tells the ribbon how to render the control, by using just the text label, the large icon, the small icon, or one of the other choices that are defined in the schema of the ControlRef element. The TemplateAlias attribute is used to call out a specific control placement. When adding controls to the group, each control's TemplateAlias attribute will match one of these TemplateAlias attributes to specify exactly where to place the control.
Now add the following markup to tell the ribbon how to render the group by using one of the layouts in the defined template.
<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>
Figure 12. Using the MsdnHorizontal layout
Figure 13. Using the MsdnVertical layout
Figure 14. Using the MsdnVerticalTextOnly layout
Step 1.3: Add Controls to the Ribbon Group
Next, add the following markup to the element manifest file to add a few buttons to the group.
Notice that each button is wired to its own command.
With the visual part of the ribbon customization completed, the next
step is to create the commands that handle both when the buttons are
available, and what they do when clicked. This is done by using command
UI handlers or page components. The next two steps will show how to do
each one.
<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>
Step 2: Create Server Ribbon Command UI Handlers
Command UI handlers are defined within the same element
manifest file that contains the ribbon visual customizations. Add the
following markup to create the first command UI handler.
This command is wired to the first button by using the Command attribute. The CommandAction
attribute executes some ECMAScript that opens a dialog box by using the
SharePoint 2010 dialog box framework that points to a custom
application page that will be created later.
Add another command UI handler that will be associated with the second button. This one does considerably more work, as shown in the following markup.
This one is a bit more complicated. First, it creates a new
ECMAScript function that will be used as a callback when the dialog box
is closed. It displays a notification in the browser, the little yellow
message that slides in from the right side of the page, and then
refreshes the List View Web Part on the page.
It then creates a delimited list of the documents selected on the current page. Finally, it creates a new dialog box that opens a new application page, and passes in the selected items. When the dialog box closes, it calls the dialogCallback method that was defined previously.
The other important piece to this is the EnabledScript attribute. This attribute returns a Boolean value of TRUE if the command is available or FALSE if it is not available. To determine this, it checks to see whether anything has been selected on the page. If not, the command, and so this button, is disabled.
<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>
Add another command UI handler that will be associated with the second button. This one does considerably more work, as shown in the following markup.
<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 +'&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>
It then creates a delimited list of the documents selected on the current page. Finally, it creates a new dialog box that opens a new application page, and passes in the selected items. When the dialog box closes, it calls the dialogCallback method that was defined previously.
The other important piece to this is the EnabledScript attribute. This attribute returns a Boolean value of TRUE if the command is available or FALSE if it is not available. To determine this, it checks to see whether anything has been selected on the page. If not, the command, and so this button, is disabled.
Step 3: Create Server Ribbon Page Component
With one button in the ribbon that uses a command that is
defined in a command UI handler, now it is time to create a page
component to handle the other command. This is done by adding a new
ECMAScript file to the Visual Studio project, ideally in a folder mapped
to the
{SharePoint Root}/TEMPLATE/LAYOUT/{ProjectName}
directory. This ensures that there is only one instance of the library on the front-end web server that is used by all sites.Step 3.1: Declare the Page Component Object
After the file is added to the project, add the following
script to the library to declare the ECMAScript object that this
library will contain, and a few constructor and initialization methods
that will create an instance of the page component and add it to the
client-side ribbon manager. This is shown in the following markup.
// 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); } }
Step 3.2: Create the Page Component Object Prototype and init Method
Now add the following script for the object prototype and
the core init method. As its name indicates, this method initializes
the object by creating a few arrays that list and map commands to
specific functions within the object.
Notice that the name of the commands in the arrays match the value of the <Button Command="" /> attribute added previously when defining the visual components of the ribbon customization.
// 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"; }, ... }
Step 3.3: Add Methods to Tell the Ribbon Manager What Commands This Page Component Handles, and How and When to Handle Commands
Next, add four methods that tell the client-side ribbon
manager what commands are available, and how and when to handle them, as
shown in the following code.
The canHandleCommand method serves the same purpose as the command UI handler's EnabledScript
attribute in that it tells the ribbon manager whether the command is
available. In the previous snippet, the method uses the array created in
the object's initializer to call a specific method in the object. The handleCommand is similar in that it serves the same purpose as the command UI handler's CommandAction attribute. It, too, uses an array to point to another method for the specified command.
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); }, ... }
Step 3.4: Add the Specific Command Methods
The next step is to add the methods that were defined in
the object's initializer and that are called to determine when the
command is available (onApplyDocPrefixPageComponent_canExecute) and what happens when the command is executed (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); }
Step 3.5: Add Final Object Registration, Initialization, and Notification Script
With the page component object complete, the last steps
are to register it on the page, create it, and tell the client-side
ribbon that anything that was waiting for this script to finish loading
it has been loaded and initialized. This is shown in the following code.
At this point, the page component has been created and can now be added to the page.
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");
Step 4: Create Server Ribbon Page Component Loader
Next, the page component must be added to the page. In this sample a custom server control is used to do this. Add a new Empty Element SharePoint project item to the project. Use the <Control /> element to register a new delegate control with the following markup.
This will add the server control PageComponentScriptLoader to the AdditionalPageHead
content placeholder to all pages in the current site, or whatever the
scope of the Feature is. Now add a new code file to the SharePoint
project item, and add the following code to implement the server
control.
This will first get a reference to the Server ribbon. When
the user is working with a document library, it will first verify that
dependent scripts are on the page, followed by registering the page
component.
The last step here is to add a <SafeControl /> entry to the site's web.config file. An Empty Element SharePoint project item does not automatically add a <SafeControl /> entry, but it does give us a way to do to it. In Solution Explorer in Visual Studio 2010, select the Empty Element. In the Properties window, click the […] builder button, as shown in Figure 15.
Figure 15. Manually adding a Safe Control Entry with SharePoint development tools in Visual Studio 2010
In the Safe Control Entries dialog box, add a new entry, and then verify that the namespace matches the namespace of the server control created earlier.
Figure 16. Safe Control Entries dialog box
<?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>
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); } }
The last step here is to add a <SafeControl /> entry to the site's web.config file. An Empty Element SharePoint project item does not automatically add a <SafeControl /> entry, but it does give us a way to do to it. In Solution Explorer in Visual Studio 2010, select the Empty Element. In the Properties window, click the […] builder button, as shown in Figure 15.
Figure 15. Manually adding a Safe Control Entry with SharePoint development tools in Visual Studio 2010
Figure 16. Safe Control Entries dialog box
Step 5: Create the Custom Dialog Box
The last step is to create the dialog box that is called by
the custom ribbon commands and that does the majority of the work. Add a
new Application Page SharePoint project item to the Visual Studio project.
Step 5.1: Implement the Visual Part of the Dialog Box (.aspx)
In this case, the dialog box uses a few of the SharePoint
administration form user controls, so a few references are needed, as
shown in the following code.
In the PlaceHolderMain content placeholder, add the following markup to create a form with an ASP.NET DataList control that will display a list of all the documents that are selected.
<%@ 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" %>
<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>
Step 5.2: Implement the Business Logic in the Code-Behind (.aspx.cs)
The code-behind for this application page is straightforward. It needs to perform the following tasks:
- Get a list of all the selected documents that are passed in on the QueryString.
- Get a reference to the list that contains the documents passed in on the QueryString.
- Show the items that are selected by binding the collection of selected documents to the ASP.NET DataList control.
- When clicked, update the file names of all the selected items.
- When finished, write some ECMAScript to the PlaceHolderAdditionalPageHead content placeholder that closes the dialog box, sending the result back to the calling page.
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>")); } }
Step 6: Deploy and Test the Custom Web Part
After saving all changes, deploy the custom Web Part by pressing F5 in Visual Studio 2010 or by clicking Start Debugging on the Debug menu.
When the initial page of the team site opens, click the Shared Documents Library. Selecting the Documents tab on the ribbon should make the ribbon customizations visible, as shown earlier in Figure 9. After a document is selected, all the buttons in the custom group will be enabled, as shown earlier in Figure 10. Clicking one of the two Apply Prefix […] buttons triggers the dialog box shown earlier in Figure 11.
When the user clicks the Set Prefix button, the dialog box updates the selected file names and then closes. The command then issues a notification message that the changes have been applied, and refreshes the List View Web Part.
When the initial page of the team site opens, click the Shared Documents Library. Selecting the Documents tab on the ribbon should make the ribbon customizations visible, as shown earlier in Figure 9. After a document is selected, all the buttons in the custom group will be enabled, as shown earlier in Figure 10. Clicking one of the two Apply Prefix […] buttons triggers the dialog box shown earlier in Figure 11.
When the user clicks the Set Prefix button, the dialog box updates the selected file names and then closes. The command then issues a notification message that the changes have been applied, and refreshes the List View Web Part.
Custom SharePoint 2010 Server Ribbon Development Tips and Tricks
When customizing the SharePoint 2010 Server ribbon,
developers have the ability to make a wide range of changes. There are
various controls that can be used, templates that could be reused, and
groups and tabs that can be modified or added to. Thankfully, the
majority of the ribbon is constructed declaratively or, in the case of
page components, resides in script files that are easily readable
compared to compiled code. This means that developers have a great
supply of code samples available to them after SharePoint is installed!
The trick is knowing where to look and how to find these examples. The base Server ribbon and all the ribbon declarations can be found in the {
The following sections help point developers in the right direction for a few common scenarios when customizing the ribbon.
The trick is knowing where to look and how to find these examples. The base Server ribbon and all the ribbon declarations can be found in the {
SharePoint Root}\TEMPLATE\GLOBAL\XML\CMDUI.XML
file in the global site definition. Additional changes made by things
like SharePoint Server 2010 Enterprise Content Management are typically
found in various Features. Simply searching all *.xml files for the <CommandUIExtension> element will show a list of all the Features that contain ribbon extensions.The following sections help point developers in the right direction for a few common scenarios when customizing the ribbon.
Finding Tab, Group, and Control Names and Sequences
One common task is to create new tabs, add groups to tabs,
or modify existing controls. The first step is finding the ID or name of
the tab. The SharePoint 2010 SDK contains a list of all tabs and their
locations. For more information, see Default Server Ribbon Customization Locations.
The names of tabs are descriptive enough that it should be obvious
which name goes with which tab. This page also contains a list of the
names of all groups and controls in these groups. The only thing missing
is the sequence and template alias.
To find the sequence and template alias, open the CMDUI.xml file and search for the relevant tab, group, or control ID listed in the SDK. This takes you to relevant entries that should answer any questions about the control.
To find the sequence and template alias, open the CMDUI.xml file and search for the relevant tab, group, or control ID listed in the SDK. This takes you to relevant entries that should answer any questions about the control.
Always Get a Clean Page Request: Clear the Browser Cache
When customizing the ribbon, developers will undoubtedly
write ECMAScript and reference images. The quantity of ECMAScript and
images and ribbon customizations depends on the complexity of the
application.
One focus of Microsoft when refactoring the SharePoint 2010 UI and developing the ribbon was to limit the weight of the page, or the combined size of all things required on a page, as much as possible. To do this, SharePoint aggressively caches CSS files and ECMAScript libraries in the browser. This in turn gives users a much faster page load time, because fewer files are requested on subsequent requests.
Although a big advantage for users, it can also create problems for developers. Changes made between debugging sessions may not appear because the browser is not downloading the latest script or customizations. As a good practice after deploying a solution and while waiting for it to load, use the Internet Explorer Developer Toolbar.
Figure 17. Clearing the IE cache and force downloads for all files
The Internet Explorer Developer Toolbar also provides a way
to explore script files. To verify that the browser has downloaded the
latest version of custom script files, use the Script
tab and select the script file that has been loaded by the page. If the
external script file is not listed, it was not added to the page. Figure
18 shows selecting the page component external script library from a
previous sample and viewing its contents.
Figure 18. Script debugging with the IE Developer Toolbar
One focus of Microsoft when refactoring the SharePoint 2010 UI and developing the ribbon was to limit the weight of the page, or the combined size of all things required on a page, as much as possible. To do this, SharePoint aggressively caches CSS files and ECMAScript libraries in the browser. This in turn gives users a much faster page load time, because fewer files are requested on subsequent requests.
Although a big advantage for users, it can also create problems for developers. Changes made between debugging sessions may not appear because the browser is not downloading the latest script or customizations. As a good practice after deploying a solution and while waiting for it to load, use the Internet Explorer Developer Toolbar.
Figure 17. Clearing the IE cache and force downloads for all files
Figure 18. Script debugging with the IE Developer Toolbar
Conclusion
This article explains the core components that make up the
Microsoft SharePoint 2010 Server ribbon. It then walks you through how
to create two sample ribbon changes that use different customization
techniques. In addition, this article also provides guidance about when
to consider the different command implementation options, either the
command UI handlers or page components, and offers some tips and tricks
for doing ribbon customization development.
No comments:
Post a Comment
Thank you for Commenting Will reply soon ......