Application Page Ribbon & Dialogs on SharePoint 2010

One of the cool new features in SharePoint 2010 is the availability of the Office Ribbon. Using the simple XML syntax, it is quite easy to add your own Ribbon controls and tabs to existing lists, libraries, and even your own web parts. You can even add contextual ribbon tabs to web parts hosted in your own custom Application Pages.

Now it’s easy to get a “global” Ribbon by simply omitting the RegistrationId and RegistrationType attributes in the Elements.xml file. You’ll find ways of doing this in tons of blog posts all over. What is not so obvious, however, is the way to do add a Ribbon to a particular Application Page when the page does not host any Web part or user control. So here’s some help for you. I’ll also take a look at interacting with a modal dialog using the new framework in SharePoint from this ribbon.

First, open up VS2010 and create an Empty SharePoint Project (make sure it’s 2010, not 2007). Next add a reference to the Microsoft.Web.CommandUI assembly as it will be needed later on.

Now create a new Application Page by right-clicking the project and adding a new item. Name it DataPage.aspx. This will get created as Layouts/<Project name>/DataPage.aspx. Now comes the interesting part. Create the ribbon by declaring two strings that hold the Tab and the GroupTemplate definitions like this:

private string mainTab = @"
    <Tab
        Id=""Ribbon.MyTab""
        Title=""My Tab""
        Description=""This is a sample tab""
        Sequence=""1105"">
    <Scaling
        Id=""Ribbon.MyTab.Scaling"">
        <MaxSize
        Id=""Ribbon.MyTab.MaxSize""
        GroupId=""Ribbon.MyTab.MyGrp""
        Size=""OneLargeTwoMedium""/>
        <Scale
        Id=""Ribbon.MyTab.Scaling.CustomTabScaling""
        GroupId=""Ribbon.MyTab.MyGrp""
        Size=""OneLargeTwoMedium"" />
    </Scaling>
    <Groups Id=""Ribbon.MyTab.Groups"">
        <Group
        Id=""Ribbon.MyTab.MyGrp""
        Description=""This is a sample group!""
        Title=""Sample Group""
        Sequence=""52""
        Template=""Ribbon.Templates.MyGrp"">
        <Controls
            Id=""Ribbon.MyTab.MyGrp.Controls"">
            <Button
            Id=""Ribbon.MyTab.MyGrp.ModalDialog""
            Sequence=""15""
            Description=""Opens a modal dialog box""
            Command=""Ribbon.MyTab.MyGrp.ModalDialog.Click""
            Image32by32=""/_layouts/images/PPEOPLE.GIF""
            LabelText=""Open Modal Dialog""
            TemplateAlias=""cust1""/>
            <Button
            Id=""Ribbon.MyTab.MyGrp.SimpleButton""
            Sequence=""17""
            Image32by32=""/_layouts/images/PPEOPLE.GIF""
            Description=""Simple alert button""
            Command=""Ribbon.MyTab.MyGrp.SimpleButton.Click""
            LabelText=""Simple Alert""
            TemplateAlias=""cust2""/>
        </Controls>
        </Group>
    </Groups>
    </Tab>";

private string contextualTabTemplate = @"
    <GroupTemplate Id=""Ribbon.Templates.MyGrp"">
    <Layout
        Title=""OneLargeTwoMedium"" LayoutTitle=""OneLargeTwoMedium"">
        <Section Alignment=""Top"" Type=""OneRow"">
        <Row>
            <ControlRef DisplayMode=""Large"" TemplateAlias=""cust1"" />
            <ControlRef DisplayMode=""Large"" TemplateAlias=""cust2"" />
        </Row>
        </Section>
    </Layout>
    </GroupTemplate>";

As you can make out, this defines a new tab with two button controls on it. Now create a OnPreRender event for the page and the following code, like so:

protected override void OnPreRender(EventArgs e)
{
    base.OnPreRender(e);

    this.AddRibbonTab();

    AddTabEvents();
}

private void AddRibbonTab()
{
    // Gets the current instance of the ribbon on the page.
    SPRibbon ribbon = SPRibbon.GetCurrent(this.Page);

    //Prepares an XmlDocument object used to load the ribbon
    XmlDocument ribbonExtensions = new XmlDocument();

    //Load the contextual tab XML and register the ribbon.
    ribbonExtensions.LoadXml(this.mainTab);
    ribbon.RegisterDataExtension(ribbonExtensions.FirstChild, 
        "Ribbon.Tabs._children");

    //Load the custom templates and register the ribbon.
    ribbonExtensions.LoadXml(this.contextualTabTemplate);
    ribbon.RegisterDataExtension(ribbonExtensions.FirstChild, 
        "Ribbon.Templates._children");

    ribbon.Minimized = false;
    ribbon.CommandUIVisible = true;
    const string initialTabId = "Ribbon.MyTab";
    if (!ribbon.IsTabAvailable(initialTabId))
        ribbon.MakeTabAvailable(initialTabId);
    ribbon.InitialTabId = initialTabId;
}

private void AddTabEvents()
{
    var commands = new List<IRibbonCommand>();

    // register the command at the ribbon. Include the callback to the server 
    // to generate the xml
    commands.Add(new SPRibbonCommand("Ribbon.MyTab.MyGrp.ModalDialog.Click", 
        "openPopup();", "true"));
    commands.Add(new SPRibbonCommand("Ribbon.MyTab.MyGrp.SimpleButton.Click", 
        "alert('goodbye cruel world');", "true"));

    //Register initialize function
    var manager = new SPRibbonScriptManager();
    var methodInfo = typeof(SPRibbonScriptManager).GetMethod(
    "RegisterInitializeFunction",
    BindingFlags.Instance | BindingFlags.NonPublic);
    methodInfo.Invoke(manager, new object[] { 
        Page, "InitPageComponent", 
        "/_layouts/SPSample/PageComponent.js", false, 
        "SPSample.PageComponent.initialize()" });

    // Register ribbon scripts
    manager.RegisterGetCommandsFunction(Page, "getGlobalCommands", commands);
    manager.RegisterCommandEnabledFunction(Page, "commandEnabled", commands);
    manager.RegisterHandleCommandFunction(Page, "handleCommand", commands);
}

The code, though a little long, is actually quite simple and can be reused almost completely for any number of ribbons. The first function simply adds the display of the ribbon while the second registers the JavaScript to call when the respective buttons’ click commands are called. The Ribbon button event handling requires some extra JavaScript as well that is loaded within another .JS file. To do this, simply add a new JavaScript file in the same location and call it PageComponent.js. This is what it’ll look like.

function ULS_SP() {
  if (ULS_SP.caller) {
    ULS_SP.caller.ULSTeamName = "Windows SharePoint Services 4";
    ULS_SP.caller.ULSFileName = "/_layouts/SPSample/PageComponent.js";
  }
}


Type.registerNamespace('SPSample');

// RibbonApp Page Component
SPSample.PageComponent = function () {
  ULS_SP();
  SPSample.PageComponent.initializeBase(this);
}


SPSample.PageComponent.initialize = function () {
  ULS_SP();
  ExecuteOrDelayUntilScriptLoaded(Function.createDelegate(null, 
    SPSample.PageComponent.initializePageComponent), 'SP.Ribbon.js');
}


SPSample.PageComponent.initializePageComponent = function () {
  ULS_SP();
  var ribbonPageManager = SP.Ribbon.PageManager.get_instance();
  if (null !== ribbonPageManager) {
    ribbonPageManager.addPageComponent(SPSample.PageComponent.instance);
    ribbonPageManager.get_focusManager().requestFocusForComponent(
    SPSample.PageComponent.instance);
  }
}


SPSample.PageComponent.refreshRibbonStatus = function () {
    SP.Ribbon.PageManager.get_instance().get_commandDispatcher().executeCommand(
  Commands.CommandIds.ApplicationStateChanged, null);
}


SPSample.PageComponent.prototype = {
  getFocusedCommands: function () {
    ULS_SP();
    return [];
  },
  getGlobalCommands: function () {
    ULS_SP();
    return getGlobalCommands();
  },
  isFocusable: function () {
    ULS_SP();
   return true;
  },
  receiveFocus: function () {
    ULS_SP();
    return true;
  },
  yieldFocus: function () {
    ULS_SP();
    return true;
  },
  canHandleCommand: function (commandId) {
    ULS_SP();
    return commandEnabled(commandId);
  },
  handleCommand: function (commandId, properties, sequence) {
    ULS_SP();
    return handleCommand(commandId, properties, sequence);
  }
}


// Register classes
SPSample.PageComponent.registerClass('SPSample.PageComponent', 
    CUI.Page.PageComponent);
SPSample.PageComponent.instance = new SPSample.PageComponent();


// Notify waiting jobs
NotifyScriptLoadedAndExecuteWaitingJobs("/_layouts/SPSample/PageComponent.js");

This code can be used as-is – other than changing the namespace (from “SPSample” in my case to whatever your code project is called).

This is actually enough for the application page to show the ribbon and have two buttons on it. The second button will in fact work fine and give an alert popup as well. For the first button, we need to use the SharePoint 2010 Modal Dialog framework. All you need to do is open the DataPage.aspx file and add the following into the PlaceHolderAdditionalPageHead.

<script language="javascript">
function demoCallback(dialogResult, returnValue) 
{
    if (dialogResult == SP.UI.DialogResult.OK)
        SP.UI.Notify.addNotification("You pressed OK, " + returnValue, false);
    else
        SP.UI.Notify.addNotification("You cancelled the operation, ", false);
}

function openPopup() 
{
    var options = {
        url: '/_layouts/SPSample/DialogPage.aspx',
        title: 'Modal Dialog',
        allowMaximize: false,
        showClose: true,
        width: 600,
        height: 500,
        dialogReturnValueCallback: demoCallback
    }

    SP.UI.ModalDialog.showModalDialog(options);
}   
</script>

Create a new Application Page and call it DialogPage.aspx. Add the following to create a simple form in the PlaceHolderMain:

<h1>Dialog popup page</h1>
<p>Please enter your name:<br />
<asp:TextBox runat="server" ID="txtFullName" /><br />
<asp:Button runat="server" ID="btnOKClient" 
    OnClientClick="btnOKClient_Click()" Text="OK (Client)" />
<asp:Button runat="server" ID="btnOKServer" 
    OnClick="btnOKServer_Click" Text="OK (Server)" />
<asp:Button runat="server" ID="btnCancel" 
    OnClientClick="btnCancel_Click()" Text="Cancel" />
</p>

This code shows a small form with one textbox and 3 buttons. The first button closes the modal dialog using the client OM directly, the second submits the form back to the server and then closes the dialog and the third simply cancels the dialog.

You will also need to add the following script in the PlaceHolderAdditionalPageHead area in the DialogPage.aspx:

<script type="text/javascript">
    function btnCancel_Click() 
    { 
       SP.UI.ModalDialog.commonModalDialogClose
           (SP.UI.DialogResult.cancel,  "Cancelled"); 
    }

    function btnOKClient_Click() 
    {
        var theForm = document.forms['aspnetForm'];
        if (!theForm) 
        {
            theForm = document.aspnetForm;
        }
        var FullName = theForm.<%= txtFullName.ClientID %>.value;
        SP.UI.ModalDialog.commonModalDialogClose(
           SP.UI.DialogResult.OK, FullName + " (Client)");
    } 
</script>

This code simply cancels the dialog on the cancel click and the on the client OK click, gets the name entered in the dialog and posts it back to show the notification.

In the code behind of the DialogPage.aspx, add an event handler for the “OK (Server)” button which looks like this:

this.Page.Response.Clear(); 
this.Page.Response.Write(
    String.Format("<script>
        window.frameElement.commonModalDialogClose(1, '{0} (Server)')
       </script>", txtFullName.Text));
this.Page.Response.End();

You can do whatever you want in the codebehind and once done, use the code above to close the dialog and send some result (in this case the same name entered in the textbox) back to the parent page.

And finally, some screenshots of how it all looks.

SP01
The custom Application Page with a custom Ribbon Tab and buttons

SP02
Clicking the “Simple Alert” button on the Tab shows, well, a simple JS alert

SP03
Clicking the “Open Modal Dialog” button open a modal dialog with another application page

SP04
The “Cancel” button in the modal dialog closes and shows a Notification message in the parent

SP05
The “OK (Client)” button in the dialog, closes the dialog and sends a notification using JS

SP06
The “OK (Server)” button submits the dialog to the server and the codebehind sends a notification back

Hope you find this useful. A big thanks to all those good people on the Web who have provided code ideas and snippets used in this article. Sorry I’m not linking to any of them as they were found while Binging around. Also, here is the entire VS2010 project in case you need it.


Tags: , , ,
Categories: Development | Office | SharePoint

18 Comments
Actions: E-mail | Permalink | Comment RSSRSS comment feed

Comments

Pingback from topsy.com

Twitter Trackbacks for
        
        Random Rants & Raves | Application Page Ribbon & Dialogs on SharePoint 2010
        [vinodunny.com]
        on Topsy.com

August 13. 2010 14:34 | topsy.com |

The link for the project download does not work....

August 24. 2010 14:08 | casey Australia |

Sorry for that. The link's been corrected now.

August 24. 2010 17:26 | vinod India |

Rather enlightening and beneficial post. You've got good command within the topic and have explained in a incredibly nice way. Thanks for sharing.

August 28. 2010 11:57 | dating websites Republic of the Philippines |

Hey very nice blog!! Man .. Beautiful .. Amazing .. I will bookmark your blog and take the feeds also...

August 31. 2010 16:31 | video games United States |

Thanks for this very useful article. To get my start up off the ground, should I make a Facebook fan page? I thought to myself, hmm before I do this, where are the fans going to come from? I have to build that customer base & relationships, then only will they become my 'fans'

September 5. 2010 15:07 | Fußmatten United States |

Hey very nice blog!! Man .. Beautiful .. Amazing .. I will bookmark your blog and take the feeds also..

August 31. 2010 17:42 | traslochi milano Italy |

Great post ....

September 3. 2010 03:45 | Samer Nazzal Jordan |

Rather enlightening and beneficial post. You've got good command within the topic and have explained in a incredibly nice way. Thanks for sharing.

September 3. 2010 21:50 | newborn gifts United States |

Hey very nice blog!! Man .. Beautiful .. Amazing .. I will bookmark your blog and take the feeds also..

September 4. 2010 19:43 | Sell Your Mobile United States |

I appear here all the time and am incredibly pleased with your updates.Thank you extremely a lot for your exceptional reality about this great subject. I could not detect this type of dissertation strategy in Internet and wanted to pay for the thesis.

September 6. 2010 08:14 | ugg ultra short United States |

There is obviously a lot to know about this. I think you made some good points in Features also. Keep working ,great job!

September 9. 2010 01:01 | Няня United States |

That's some inspirational stuff. Certainly not knew that opinions might be this diverse. Thank you for all of the enthusiasm to provide such valuable facts right here. I’m really very interested so will maintain an eye out for updates!

September 9. 2010 05:57 | Nike Dunk High United States |

It seems like a very good web site but my English is not good. It would be great if it might be availible in other languages too. But, I like this web site very much, thank you very much share this information.

September 9. 2010 17:33 | Yurtdışı Eğitim Turkey |

The site was informative and contain useful content for the visitors. It got good posts as well. I will bookmark this site for future viewing. Thanks for sharing. Regards

September 9. 2010 22:33 | bark off United States |

Rather enlightening and beneficial post. You've got good command within the topic and have explained in a incredibly nice way. Thanks for sharing.

September 11. 2010 01:35 | inspection United States |

Your weblog is so fantastic that I arrive right here lots of times. I like searching on-line. Searching on the net is actually a bargain simply because you can actually continually get a discount. But the lure of browsing over the internet vs. purchasing in shop splits the pundits.

September 11. 2010 07:53 | Nike Dunk High United States |

Pingback from downloadmicrosoftoffice.everniche.com

Application Page Ribbon & Dialogs on SharePoint 2010

January 21. 2011 00:51 | downloadmicrosoftoffice.everniche.com |

Comments are closed