Thursday, January 9, 2014

Creating Ribbon Tabs and Buttons in Visual Studio Part 1

A few weeks ago I published a post on this using pure javascript code directly from a page. That code was in the site assets library and added to a Content Editor Web Part (CEWP). You can check that post out here.

The main goal of that post was to prove that it is possible to create a custom tab in javascript. Even though the base method for doing this uses an OOB SharePoint javascript function, it does not use the more “approved” method for creating custom ribbon components. It does allow you to create content in the ribbon area using jQuery/javascript that you would not otherwise be able to do using the “approved” methods. That will be touched on more in a future post possibly part 2 of that initial one.

As stated, there is an “approved” (or maybe “supported” is a better term for it) method for creating custom ribbon components. The ribbon is mostly “drawn” from declarative XML referred to as Ribbon XML and there is a lot of documentation that covers it on MSDN. This declarative approach makes it easy to create fairly complex tabs and controls. Much of the OOB ribbon is defined in the Program Files\Common Files\microsoft shared\Web Server Extensions\14\TEMPLATE\GLOBAL\XML\CMDUI.XML file. I have referenced this file to create several different ribbon components. (Note that for SharePoint 2013 this would be in the 15 folder)

If you take a look at the ribbon, you can see that there are several types of controls that you can create. There are 2 main tab types. A regular tab and what is called a contextual tab. A contextual tab is a tab that is only available when an object on a page is selected. This tab contains sub tabs with groups of buttons representing commands for customizing/formatting the selected object. An example from PowerPoint is below:

As you can see, this allows us to create some very nice controls based on what we want to do. So lets create something so that we can see this stuff in action.

We are going to create a new solution in Visual Studio. I am using Visual Studio 2012. For my example I also used some OOB images from the layouts/images folder. I copied the MENUOUTL.GIF file and used Adobe After Effects to change the color just to make a different icon for contrast. You can use any icon you like of course!

So start Visual Studio and create a new Project as shown below:


Click OK and then select the type of solution. This brings up the next screen where I chose a farm solution.


Click Finish to get into the solution.

Once in the solution, you will need to create an Empty Element. Right click on the C# project as highlighted below:


This will bring up a selection menu where you will select “Add” and then “New Item” as shown below:


Which will then bring up the next screen:


Give it a good name and as you can see, I named it "E3D_Email_Tab2". This will create an elements.xml file. This is where the Ribbon XML code is declared.


Of course this is an empty file and we need something to add here! Copy in the below code and I will go over it.

1 <?xml version="1.0" encoding="utf-8"?> 2 <Elements xmlns=""> 3 <CustomAction 4 RegistrationType="ContentType" RegistrationId="0x01" 5 Id="E3D.Utilities.Mail2" 6 Sequence="1010" 7 Location="CommandUI.Ribbon"> 8 <CommandUIExtension> 9 <CommandUIDefinitions> 10 <CommandUIDefinition 11 Location="Ribbon.Tabs._children"> 12 <Tab 13 Id="E3D.Utilities.Tab2" 14 Title="E3D Utilities 2" 15 Description="This tab holds custom commands for EMail and other operations." 16 Sequence="2500"> 17 <Scaling 18 Id="E3D.Utilities.Tab.Scaling"> 19 <MaxSize 20 Id="E3D.Utilities.Tab.One.Scaling.MaxSize" 21 GroupId="E3D.Utilities.Tab.GroupOne" 22 Size="TwoLarge"/> 23 <Scale 24 Id="E3D.Utilities.Tab.One.Scaling.Scale" 25 GroupId="E3D.Utilities.Tab.GroupOne" 26 Size="TwoLarge" /> 27 </Scaling> 28 <Groups Id="E3D.Utilities.Tab.Groups"> 29 <Group 30 Id="E3D.Utilities.Tab.GroupOne" 31 Description="" 32 Title="E-Mail" 33 Sequence="10" 34 Template="E3D.Utilities.RibbonTemplate.Outlook"> 35 <Controls Id="E3D.Utilities.Tab.GroupOne.Controls"> 36 <SplitButton 37 Id="E3D.Utilities.Tab.GroupOne.EmailAllUsers" 38 Command="E3D.Utilities.EmailAllCC" 39 Sequence="10" 40 ToolTipTitle="Email All Options." 41 ToolTipDescription="Email All Options." 42 Image16by16="/_layouts/images/outl.gif" 43 Image32by32="~sitecollection/_layouts/Images/menuoutl.gif" 44 LabelText="Email All:" 45 PopulateDynamically="false" 46 PopulateOnlyOnce="true" 47 TemplateAlias="customOne"> 48 <Menu Id="E3D.Utilities.Tab.GroupOne.AllEmailDropDown.Menu"> 49 <MenuSection Id="E3D.Utilities.Tab.GroupOne.AllEmailDropDown.Menu.MenuSectionOne"> 50 <Controls Id="E3D.Utilities.Tab.GroupOne.AllEmailDropDown.Menu.Controls"> 51 <Button 52 Id="E3D.Utilities.Tab.GroupOne.AllEmailDropDown.Menu.CC" 53 Command="E3D.Utilities.EmailAllCC2" 54 LabelText="Email All as CC" /> 55 <Button 56 Id="E3D.Utilities.Tab.GroupOne.AllEmailDropDown.Menu.BCC" 57 Command="E3D.Utilities.EmailAllBCC2" 58 LabelText="Email All as BCC"/> 59 </Controls> 60 </MenuSection> 61 </Menu> 62 </SplitButton> 63 <SplitButton 64 Id="E3D.Utilities.Tab.GroupOne.EmailSelectedUsers" 65 Command="E3D.Utilities.EmailSelectedCC" 66 Sequence="20" 67 ToolTipTitle="Email Selected Options." 68 ToolTipDescription="Email Selected Options." 69 Image16by16="/_layouts/images/outl.gif" 70 Image32by32="~sitecollection/_layouts/Images/menuoutl2.jpg" 71 LabelText="Email Selected:" 72 PopulateDynamically="false" 73 PopulateOnlyOnce="true" 74 TemplateAlias="customTwo"> 75 <Menu Id="E3D.Utilities.Tab.GroupOne.SelectedEmailDropDown.Menu"> 76 <MenuSection Id="E3D.Utilities.Tab.GroupOne.SelectedEmailDropDown.Menu.MenuSectionOne"> 77 <Controls Id="E3D.Utilities.Tab.GroupOne.SelectedEmailDropDown.Menu.Controls"> 78 <Button 79 Id="E3D.Utilities.Tab.GroupOne.SelectedEmailDropDown.Menu.CC" 80 Command="E3D.Utilities.EmailSelectedCC2" 81 LabelText="Email Selected as CC" /> 82 <Button 83 Id="E3D.Utilities.Tab.GroupOne.SelectedEmailDropDown.Menu.BCC" 84 Command="E3D.Utilities.EmailSelectedBCC2" 85 LabelText="Email Selected as BCC"/> 86 </Controls> 87 </MenuSection> 88 </Menu> 89 </SplitButton> 90 </Controls> 91 </Group> 92 </Groups> 93 </Tab> 94 </CommandUIDefinition> 95 <CommandUIDefinition Location="Ribbon.Templates._children"> 96 <GroupTemplate Id="E3D.Utilities.RibbonTemplate.Outlook"> 97 <Layout 98 Title="TwoLarge" 99 LayoutTitle="TwoLarge"> 100 <Section Alignment="Top" Type="OneRow"> 101 <Row> 102 <ControlRef DisplayMode="Large" TemplateAlias="customOne" /> 103 <ControlRef DisplayMode="Large" TemplateAlias="customTwo" /> 104 </Row> 105 </Section> 106 </Layout> 107 </GroupTemplate> 108 </CommandUIDefinition> 109 </CommandUIDefinitions> 110 <CommandUIHandlers> 111 <CommandUIHandler 112 Command="E3D.Utilities.EmailAllCC2" 113 CommandAction="javascript: var notifythem = ''; this.notifythem = SP.UI.Notify.addNotification('This would email everyone!', false);" /> 114 <CommandUIHandler 115 Command="E3D.Utilities.EmailSelectedCC2" 116 CommandAction="javascript: var notifythem = ''; this.notifythem = SP.UI.Notify.addNotification('This would email only a select few!', false);" /> 117 <CommandUIHandler 118 Command="E3D.Utilities.EmailAllBCC2" 119 CommandAction="javascript: var notifythem = ''; this.notifythem = SP.UI.Notify.addNotification('This would blindly do some emailing!', false);" /> 120 <CommandUIHandler 121 Command="E3D.Utilities.EmailSelectedBCC2" 122 CommandAction="javascript: var notifythem = ''; this.notifythem = SP.UI.Notify.addNotification('So would this one!', false);" /> 123 </CommandUIHandlers> 124 </CommandUIExtension> 125 </CustomAction> 126 </Elements> 127

As you can see, that is a lot of XML, but not too much!

The first thing that is defined is that this is a CustomAction. We give this some attributes as follows:

  • RegistrationType: This defines what type of item we are registering the custom action to. (Ex. Content Type)
  • RegistrationId: This defines the id of the item. (Ex. 0x01 = default item content type id)
  • Id: This is a unique identifier for the custom action
  • Sequence: Defines the order
  • Location: Defines where the custom action is placed. These can be found here for 2010 and here for 2013.

Then we move to the real meat of the XML by defining a CommandUIExtension with some CommandUIDefinitions. A CommandUIDefinition has the Location parameter as well denoting where it will be placed.

Tab: For this I defined a Tab item with the attributes as shown in the above XML. Again a unique id is given and also a Title that defines what is displayed in the tab as seen in the image shown below.

Scaling: The next thing I defined was the scaling. This is used to define what happens to your controls as the size of the ribbon changes. In my example, I chose to do nothing as there are only 2 controls. Again, there are several options here as defined in the RibbonXML documentation.

Groups: A place to add the groups for this single tab.

Group: This defines a single group with the attributes as shown.

Controls: This is where the real fun begins and you define the controls you want to use. In this example I used 2 SplitButton controls. This is simply a button with a dropdown menu.

Some nice attributes are defined in the controls and one of the nice ones is the Image32by32 and Image16by16. These define the location of the images that will be used by the controls. These attributes are available in many of the supported ribbon controls.

Another important attribute to include is the Command attribute of your control. This is the name or id of the command. This will then be used to define what to when that item is used.

There is also the TemplateAlias attribute. This is a somewhat unique identifier that is used later when defining the layout of the group.

And for that segue lets get to the next CommandUIDefiniton which is the Templates which is used to setup the group layouts, sections and rows as seen in the above XML. And notice the TemplateAlias names match.

After we have defined what controls we want and have decided where they go and what they look like, it is time to define what happens when the control is used. For this we define a CommandUIHandlers section with a CommandUIHandler for each command we want to handle. There are a few ways to do this. First, you define the Command you want to handle and then have the option of defining a CommandAction. In general this is some javascript code that does some action. If what you are doing is complex code, you may want to move the javascript to a different file. This file could be in the master page, or you could use a CommandAction to load javascript file. This will be explained in the next post.

So, lets look at what deploying this yields.

Remember I changed one of my icons for contrast as shown below.


I already had another solution which is why there are 2 custom tabs, but as you can see, they are pretty cool. You can take this pretty far if you want to really create some nice stuff. My next post on this topic will include adding controls to existing ribbons and groups and maybe a few more types of controls. Stay tuned, and as always, let me know what you think and if there is something you would like me to post about.