SharePoint 2010 + Document Sets + Custom Ribbon Buttons with Custom Code

I recently posted a guide on how to add an item to the SharePoint 2010 context menu (“EditControlBlock”) and run some custom code on the click action. SharePoint 2010 uses the love-it-or-hate-it Microsoft Ribbon, which, to the developer, is fully accessible. This guide will show you how to implement a custom button for a Document Set, in the Manage group and also on the Edit form, and run some custom code when it’s clicked, in Visual Studio 2010.

There are three components you need to do this:

  • Your ribbon buttons
  • A delegate action that ties up your buttons to your
  • Custom code that should run

I’ll quickly skim through the process.

  1. Create a new empty SharePoint 2010 project, Deploy as a Farm Solution
  2. Note: if you change the name of your project, which you likely will, then the default namespace of your project will change to the project name. In this example, my project is called SharePointProject1, so I have a namespace of SharePointProject1. Therefore, whereever you see SharePointProject1, you should replace it with the namespace of your project.
  3. Right click the project and add a New Empty Element, call it RibbonButton
  4. In your empty element, create the code for your button
  5. Version 1: a button in the Manage group in the main ribbon, which appears when you’re looking at a document set.

    <elements xmlns="http://schemas.microsoft.com/sharepoint/">
      <customaction Location="CommandUI.Ribbon" RegistrationId="0x0120D520" RegistrationType="ContentType" Title="Custom Document Set Button" Id="Ribbon.Documents.DocsetButton">
        <commanduiextension>
          <commanduidefinitions>
            <commanduidefinition Location="Ribbon.ManageDocumentSet.MDS.Manage.Controls._children">
              <button Id="Ribbon.ManageDocumentSet.MDS.Manage.Controls.CustomButton" TemplateAlias="o1" ToolTipDescription="Demonstrate a ribbon doing something cool" ToolTipTitle="Download as Zip" LabelText="Weeeee" Image32by32="/_layouts/images/zipfile32x.png" Image16by16="/_layouts/images/zipfile16x.png" Alt="Weee" Command="Ribbon.ManageDocumentSet.MDS.Manage.CustomButtonClick" Sequence="20"></button>
            </commanduidefinition>
          </commanduidefinitions>
          <commanduihandlers>
            <commanduihandler Command="Ribbon.ManageDocumentSet.MDS.Manage.CustomButtonClick" CommandAction="javascript:__doPostBack('MyDelegateEvent', '')"></commanduihandler>
          </commanduihandlers>
        </commanduiextension>
      </customaction>
    </elements>
    

    or alternatively, to add a button to the Document Set edit form:

    <elements xmlns="http://schemas.microsoft.com/sharepoint/">
      <customaction Location="CommandUI.Ribbon.EditForm" RegistrationId="0x0120D520" RegistrationType="ContentType" Title="Custom Document Set Button" Id="Ribbon.Documents.DocsetButton">
        <commanduiextension>
          <commanduidefinitions>
            <commanduidefinition Location="Ribbon.DocLibListForm.Edit.Actions.Controls._children">
              <button Id="Ribbon.ManageDocumentSet.MDS.Manage.Controls.CustomButton" TemplateAlias="o2" ToolTipDescription="Demonstrate a ribbon doing something cool" ToolTipTitle="Download as Zip" LabelText="Weeeee" Image32by32="/_layouts/images/zipfile32x.png" Image16by16="/_layouts/images/zipfile16x.png" Alt="Weee" Command="Ribbon.ManageDocumentSet.MDS.Manage.CustomButtonClick" Sequence="20"></button>
            </commanduidefinition>
          </commanduidefinitions>
          <commanduihandlers>
            <commanduihandler Command="Ribbon.ManageDocumentSet.MDS.Manage.CustomButtonClick" CommandAction="javascript:__doPostBack('MyDelegateEvent', '')"></commanduihandler>
          </commanduihandlers>
        </commanduiextension>
      </customaction>
    </elements>
    
  6. A couple of things to say about the above. The Command attribute of the Button element should be the same as the Command attribute of the CommandUIHandler element. This is what ties the two together. Secondly: the templateAlias attribute is annoyingly important! I found that if you have it set incorrectly, then the button won’t display at all. According to the docs, “o1” is to display a large image, whereas “o2” is to display a small image. However, it seems that the main ribbon only supports “o1” and the EditForm ribbin only supports “o2”.
  7. For a full list of locations that you may want to add buttons, view this page: http://msdn.microsoft.com/en-us/library/ee537543.aspx
  8. Now, add a Class file to your project, called “MyClass”
  9. The guts of the class should look like this:
  10. using System.IO;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.WebControls;
    using System.Web.UI.WebControls;
    
    namespace SharePointProject1
    {
        public class MyClass : WebControl
        {
            const string MYEVENT = "MyDelegateEvent";
    
            protected override void OnLoad(EventArgs e)
            {
                this.EnsureChildControls();
                base.OnLoad(e);
                if (this.Page.Request["__EVENTTARGET"] == MYEVENT)
                {
    // custom code here
                    int itemId = Convert.ToInt32(this.Page.Request["__EVENTARGUMENT"]);
                    System.IO.TextWriter mywriterFired = new StreamWriter(@"C:\zzz_CodeBehindFileItemMenu.txt", true);
                    mywriterFired.WriteLine("Event Fired at:" + DateTime.Now.ToLongTimeString() + ": Item ID:" + itemId.ToString());
                    mywriterFired.Close();
                }
            }
    
        }
    }
    

    I’m just reusing the code in my previous example, which writes out a text file, but this where you can do whatever you want with your custom code.

  11. Now, build the project, and then Deploy.
  12. Head to C:Windowsassembly, find the SharePointProject1 .dll and note down the PublicKeyToken in its properties.
  13. Now update your web.config to add a SafeControls entry:
  14. <safecontrol Assembly="SharePointProject1", Version=1.0.0.0, Culture=neutral, PublicKeyToken={token}" Namespace="SharePointProject1" TypeName="*" Safe="True"></safecontrol>
    
  15. Now, back in your project, add a second Empty Element to your project called RibbonButtonDelegate
  16. Update the Elements.xml file to look like this:
  17. <elements xmlns="http://schemas.microsoft.com/sharepoint/">
      <control ControlClass="SharePointProject1.MyClass" 
        ControlAssembly="SharePointProject1, Version=1.0.0.0, Culture=neutral, PublicKeyToken={token}" 
        Sequence="50" Id="AdditionalPageHead"></control>
    </elements>
    

    Replacing {token} with the token you noted down.

  18. Add a feature to your project. Open the feature and ensure both of your Elements are in the feature. Set the scope to Web.
  19. Deploy your project (right click the Project > Deploy.)
  20. Restart IIS
  21. Navigate to a Document Library which has Document Sets enabled, and browse in to Document Set. Depending on which button you created (or both) you should now see a new button in the Manage group or in the Edit Properties form.
  22. Click the button, and your code should run.

Happy days.

11 Comments

  1. Is it possible to modify this code so that you replace an existing button in the “New Document” group of the ribbon? I would like to have some custom code added to the “New Document” button. If so, could you demonstrate?

  2. Dear,

    i need to enable true the button,when the user selects the document from the list ,otherwise the button should be in disabled mode,how can i do that?

    Thanks
    Ram

  3. Found solution…. To work your code I have to put in class the following code:
    public class CustomItemAction : WebControl
    {
    public string MYEVENT = “RunWorkflow”;
    protected override void CreateChildControls()
    {
    if (this.Page.Request[“__EVENTTARGET”] == MYEVENT)
    {
    System.IO.TextWriter mywriterFired = new StreamWriter(@”C:a.txt”, true);
    mywriterFired.WriteLine(“Event Fired at:” + DateTime.Now.ToLongTimeString() + “: Item ID:”);
    mywriterFired.Close();
    }
    }
    }

  4. Hi Matt. Are you sure that this code works?? I modificated de xml like this:
    Id=”Hello_world”
    RegistrationType=”List”
    RegistrationId=”101″
    Location=”CommandUI.Ribbon”
    Sequence=”5″>

    <Button

    To put the button in the documments, but the event never firing….

  5. Hi Vishal. What do you mean On Click? Because a standard List Item event receiver would work, depending on what you mean. Also, you can attach context menu to items of specific content types, so maybe that would work too. I’ve got a post about it elsewhere on the blog.

  6. hi ,
    nice and helpful blog Matt

    i have scenario to enable a button for selection of document inside a document set and perform some action on click for particular selected document , please suggest me what are the modification to take up from above blog .

    thanks a lot

1 Trackback / Pingback

  1. Quick tip: SPListItem.CopyTo custom method « Thornton Technical

Leave a Reply

Your email address will not be published.


*