19JAN 2013

SP 2013: Some new DelegateControl additions to the SharePoint 2013 master pages


Posted by Tobias Zimmergren
TwentyThirteenDelegateControls

Author: Tobias Zimmergren
http://www.zimmergren.net | http://www.tozit.com | @zimmergren

Introduction

In this post we’ll take a quick look at some of the new DelegateControls I’ve discovered for SharePoint 2013 and how you can replace or add information to your new master pages using these new controls, without modifying the master pages. This is done exactly the same way as you would do it back in the 2010 projects (and 2007), the only addition in this case are a few new controls that we’ll investigate.

New DelegateControls

Searching through the main master page, Seattle.master, I’ve found these three new DelegateControls:

  • PromotedActions
  • SuiteBarBrandingDelegate
  • SuiteLinksDelegate

So let’s take a look at where these controls are placed on the Master page and how we can replace them.

PromotedActions Delegate Control

The PromotedActions delegate control allows you to add your own content to the following area on a SharePoint site in the top-right section of the page:

image

An example of adding an additional link may look like this:

image

So what does the files look like for these parts of the project?

Elements.xml

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    
  <!-- DelegateControl reference to the PromotedActions Delegate Control -->
  <Control ControlSrc="/_controltemplates/15/Zimmergren.DelegateControls/PromotedAction.ascx"
           Id="PromotedActions"
           Sequence="1" />
  
</Elements>

PromotedActions.aspx (User Control)

<!-- Note: I've removed the actual Facebook-logic from this snippet for easier overview of the structure. -->
<a title="Share on Facebook" class="ms-promotedActionButton" style="display: inline-block;" href="#">
    <span class="s4-clust ms-promotedActionButton-icon" style="width: 16px; height: 16px; overflow: hidden; display: inline-block; position: relative;">
        <img style="top: 0px; position: absolute;" alt="Share" src="/_layouts/15/images/Zimmergren.DelegateControls/facebookshare.png"/>
    </span>
    <span class="ms-promotedActionButton-text">Post on Facebook</span>
</a>

SuiteBarBrandingDelegate Delegate Control

This DelegateControl will allow you to override the content that is displayed in the top-left corner of every site. Normally, there’s a text reading "SharePoint" like this:

image

If we override this control we can easily replace the content here. For example, most people would probably like to add either a logo or at least make the link clickable so you can return to your Site Collection root web. Let’s take a look at what it can look like if we’ve customized it (this is also a clickable logo):

image

So what does the files look like for this project?

Elements.xml

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    
  <!-- SuiteBarBrandingDelegate (the top-left "SharePoint" text on a page) -->
  <Control ControlSrc="/_controltemplates/15/Zimmergren.DelegateControls/SuiteBarBrandingDelegate.ascx"
           Id="SuiteBarBrandingDelegate"
           Sequence="1" />
  
</Elements>

SuiteBarBrandingDelegate.ascx (User Control)

This is the only content in my User Control markup:

<div class="ms-core-brandingText" id="BrandingTextControl" runat="server" />

SuiteBarBrandingDelegate.ascx.cx (User Control Code Behind)

protected void Page_Load(object sender, EventArgs e)
{
    BrandingTextControl.Controls.Add(new Literal
    {
        Text = string.Format("<a href='{0}'><img src='{1}' alt='{2}' /></a>", 
        SPContext.Current.Site.Url,
        "/_layouts/15/images/Zimmergren.DelegateControls/tozit36light.png",
        SPContext.Current.Site.RootWeb.Title)
    });
}

SuiteLinksDelegate Delegate Control

The SuiteLinksDelegate control will allow us to modify the default links, and to add our own links, in the "suit links" section:

image

By adding a custom link to the collection of controls, it can perhaps look like this:

image

What does the project files look like for modifying the SuiteLinksDelegate? Well, here’s an example:

Elements.xml

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  
  <!-- DelegateControl reference to the SuiteLinksDelegate Delegate Control -->
  <Control ControlSrc="/_controltemplates/15/Zimmergren.DelegateControls/SuiteLinksDelegate.ascx"
           Id="SuiteLinksDelegate"
           Sequence="1" />
  
</Elements>

 

SuiteLinksDelegate.aspx.cs (User Control Code Behind)

public partial class SuiteLinksDelegate : MySuiteLinksUserControl
{
    protected override void Render(HtmlTextWriter writer)
    {
        writer.RenderBeginTag(HtmlTextWriterTag.Style);
        writer.Write(".ms-core-suiteLinkList {display: inline-block;}");
        writer.RenderEndTag();
        writer.AddAttribute(HtmlTextWriterAttribute.Class, "ms-core-suiteLinkList");
        writer.RenderBeginTag(HtmlTextWriterTag.Ul);
            
        // The true/false parameter means if it should be the active link or not - since I'm shooting off this to an external URL, it will never be active..
        RenderSuiteLink(writer, "http://timelog.tozit.com", "Time Report", "ReportYourTimeAwesomeness", false);

        writer.RenderEndTag();
        base.Render(writer);
    }
}

Solution overview

For reference: I’ve structured the project in a way where I’ve put all the changes into one single Elements.xml file and they’re activated through a Site Scoped feature called DelegateControls. The solution is a Farm solution and all artifacts required are deployed through this package.

image

Summary

In this post we’ve looked at how we can customize some of the areas in a SharePoint site without using master page customizations. We’ve used the good-old approach of hooking up a few Delegate Control overrides to our site collection. Given the approach of Delegate Controls, we can easily just de-activate the feature and all our changes are gone. Simple as that.

In SharePoint 2013 we can still do Delegate Control overrides just like we did back in 2007 and 2010 projects, and it’s still pretty slick. I haven’t investigated any other master pages other than the Seattle.master right now – perhaps there’s more new delegate controls somewhere else. Let’s find out..

Enjoy.

  • Pingback: SP 2013: Tip – Change the "SharePoint" text in the top left corner. | Tobias Zimmergren's thoughts on development

  • jignesh(sharepointempower.com)

    Great stuff !!! thanks for sharing.

    • http://www.zimmergren.net/ Tobias Zimmergren

      Thank you jignesh.

  • http://www.facebook.com/fmigacz Frank Migacz

    Can I scope the solution to the SPSite and run this in a sandbox (SharePoint Online)?

    • http://twitter.com/blksthl Thomas Balkeståhl

      Hi Tobias, great post.
      I have the same q as Frank, or almost, does this work in SPO 2013? Or is there any special modification needed?

  • http://twitter.com/christou Christian SU

    Good post :) Notice that for SuiteBarBrandingDelegate, the HTML is a SPWebApplication property : SPContext.Current.Site.WebApplication.SuiteBarBrandingElementHtml ;-)

    I did an admin application page + custom action to edit it to confirm that

  • CBL

    For the suite delegate links, any way to have them open in a new window? There is no override for that in RenderSuiteLink..

    • http://www.zimmergren.net/ Tobias Zimmergren

      Hi CBL,

      I haven’t looked into that myself, but I’m pretty confident it’s possible to do one way or the other. Since you can set attributes on your links (like: writer.AddAttribute(HtmlTextWriterAttribute.Class, “ms-core-suiteLinkList”); for example) then perhaps you can tag it with a custom class and have some jQuery magic take care of opening that link in a new window. Shouldn’t be too hard to accomplish that.
      As for any built-in way to have them open in a new window: I don’t know. But what I posted above should be possible.
      Cheers,
      Tobias.

  • http://twitter.com/pieterodb Pieter Op De Beeck

    Hi, good article! Do you think it is possible to add a drop-down menu in

    SuiteLinksDelegate- area?

    • http://www.zimmergren.net/ Tobias Zimmergren

      Hi Pieter,
      Just like I replied to CBL here below just now, I think you can do that using jQuery quite easily. Have a link render like normal and then append some jQuery and CSS magic on top of that to make a drop down. I don’t have any code samples at hand for this right now, but it should absolutely be possible :-)
      Cheers,
      Tobias.

  • Jude

    Thanks very much, this article makes my branding work much more easier. I was using css to cover the suitebar text. but it is still there when the page is loading.

    • http://www.zimmergren.net/ Tobias Zimmergren

      Hi Jude,
      I’m glad you liked it.
      Cheers,
      Tobias.

  • http://twitter.com/ekerot Peter Ekerot

    A shame that SuiteLinksDelegate is not really extensible. This solution breaks the semantics of the outputted HTML putting two UL’s after another, instead of letting us actually add LI elements to the parent unordered list of links. (hence the style-trick with inline-block, of course). Would have been nice if the delegatecontrol had allowed multiple controls instead, or another way to inject our own links “inline”.

  • http://twitter.com/wesmacdonald Wes MacDonald

    Great post!

    • http://www.zimmergren.net/ Tobias Zimmergren

      Thank you Wes, appreciated.
      Tob.

  • Mahdi Kamani

    Hi,

    I’ve just apply your method to add a custom link to suite bar links but after deploying suite bar links go hidden and I can’t bring them back to my site….Any help or idea ?

    thanks in advance.

    • http://www.zimmergren.net/ Tobias Zimmergren

      Hi Mahdi,
      That doesn’t sound very good :-)
      Can you please reproduce the steps and share the code you’ve used so I know what you’ve done?
      None of the code in my article actually removes anything – it only replaces or adds things with your own custom controls. What differs your implementation from any of the above?
      Cheers,
      Tobias.

      • Rapati

        Hi,
        Even I followed the same on this article. It was working good in the development environment, not in the production. Once I activate the feature, all of the suite bar links are gone.
        Looks like something is broken.

      • Mahdi Kamani

        Hi Tobias,

        The code that I used in my project is exactly as same as yours but the only part that I think makes difference is RenderSuiteLink function. Here is the code that I use for this function:

        protected static void RenderSuiteLink(HtmlTextWriter writer, string url, string name, string linkId)

        {

        writer.AddAttribute(HtmlTextWriterAttribute.Class, “ms-core-suiteLink”);

        writer.RenderBeginTag(HtmlTextWriterTag.Li);

        writer.AddAttribute(HtmlTextWriterAttribute.Class, “ms-core-suiteLink-a”);

        writer.AddAttribute(HtmlTextWriterAttribute.Href, url);

        writer.AddAttribute(HtmlTextWriterAttribute.Id, linkId);

        writer.RenderBeginTag(HtmlTextWriterTag.A);

        writer.AddAttribute(HtmlTextWriterAttribute.Class, “ms-verticalAlignMiddle”);

        writer.RenderBeginTag(HtmlTextWriterTag.Span);

        writer.Write(name);

        writer.RenderEndTag();

        }

        }

        Thanks in advance
        Mahdi.