Creating a Custom Welcome Menu for SharePoint Server 2010 – Part 1

Part 1 – Overview, Profile Picture, and User Name

A project I am working on called for a custom implementation of the SharePoint Welcome menu control. The replacement control needed to provide the following:

  • Implement the look and behaviors that the designers created.
  • Exclude some default SharePoint menu items (such as My Regional Settings).
  • Reuse some existing SharePoint menu items (such as Sign Out/Sign in as a Different User).
  • Allow for the addition of other custom menu items in the future.
  • Display thumbnail of the user’s profile picture.

I had to create a control that looked and behaved like the following:

CropperCapture[2]

The designers came up with some clean, semantic markup married with some jquery, for me to start from:

<div class="header">

    <img class="header-logo" src="/images/header_logo.png" alt="" width="169" height="78" />

    <div class="header-bar">

        <div class="profile_menu">

            <a href="#" class="profile_btn">

                <span class="image"><img src="" style="width:20px;height:20px" /></span>

                <span class="name">John Doe</span>

                <span class="arrow"></span>

            </a>

            <div class="profile_dropdown">

                <div class="dropdown_bkgrd">

                    <ul>

                        <li>Edit Profile</li> 

                        <li>My Site</li>

                        <li>Log Out</li>                        

                        <li>Sign in as a Different User</li>

                    </ul>

                </div>

            </div>

        </div>

    </div>

</div>

This is part 1 of a three part series.

    1. Part 1 – Overview, Profile Picture, and User Name
    2. Part 2 – Edit Profile and My Site links
    3. Part 3 – Sign Out/Sign in as a Different User

Overview of Approach

My general approach to solve this was to create a .NET User Control, installed in the _controltemplates directory. I could use code-behind and the API, and have the most control over display and formatting of the menu. This could all be deployed with a WSP package, using Visual Studio 2010. I could leave out any menu items I didn’t need, add any custom items necessary, and write code to recreate any SharePoint menu items that I wanted to keep.

I started out creating a new Empty SharePoint Project in Visual Studio 2010:

image

I then added a User Control to the project, and pasted the markup from the designers into the :

image

My next task was to figure out what I could reuse from SharePoint’s own menus, by looking into the OOB Welcome menu.

OOB Welcome Menu Controls

Before I started, I had to dissect the out-of-box Welcome menu control. If you look at the master pages in SharePoint, they usually include a reference to Welcome.ascx. It turns out that this isn’t just one control, it is a combination of three different controls that each interject their own menu items:

  1. Microsoft.SharePoint.WebControls.PersonalActions – This is the primary control, responsible for most of the menu items and the menu core. Items 4-9 below (plus another item, “Request Access” that isn’t shown in the screen shot) are rendered by this control. The menu and its items are rendered as <menu> and <ie:menuitem> nodes in the html.
  2. Microsoft.SharePoint.WebControls.MUISelector – This is responsible for displaying language selections (item #3 below) if you’ve installed language packs.
  3. Microsoft.SharePoint.Portal.WebControls.SocialNavigationControl – This is responsible for displaying My Site and My Profile links (items 1 and 2 below, part of SharePoint Server).

default-welcome-menu2

Displaying the User’s Profile Picture

To display the profile picture, I first had to adjust the original markup from the designers to include a server Image control. Here is the original markup:

<a href="#" class="profile_btn">

    <span class="image><img src="" style="width:20px;height:20px;" /></span>

    <span class="name">John Doe</span>

    <span class="arrow"></span>

</a>

Here is the adjusted markup:

<a href="#" class="profile_btn">

    <span class="image"><asp:Image ID="imageProfilePicture" runat="server" Width="20px" Height="20px" /></span>

    <span class="name">John Doe</span>

    <span class="arrow"></span>

</a>

Once that was done, I was able to use the API to get at the user’s picture:

protected void Page_PreRender(object sender, EventArgs e)

{    

    // Profile picture

    SPList userInfoList = SPContext.Current.Web.GetCatalog(SPListTemplateType.UserInformation);

    SPListItem userProfileItem = userInfoList.GetItemById(SPContext.Current.Web.CurrentUser.ID);

    if (userProfileItem["Picture"] == null || string.IsNullOrEmpty(userProfileItem["Picture"].ToString()))

    {

        // Use default picture (or replace with another)

        imageProfilePicture.ImageUrl = "/_layouts/images/PERSON.GIF";

    }

    else

    {

        SPFieldUrlValue value = new SPFieldUrlValue(userProfileItem["Picture"].ToString());

        imageProfilePicture.ImageUrl = value.Url;

    }

}

Displaying the User’s Name

The user name is pretty easy to deconstruct. The PersonalActions menu uses the PostCacheSubstitutionText control to render the user name and insert it into the Welcome menu’s controls collection (code below from Reflector):

PostCacheSubstitutionText child = new PostCacheSubstitutionText();

if (flag)

{

    child.TextType = PostCacheSubstitutionTextType.UserName;

}

else

{

    child.TextType = PostCacheSubstitutionTextType.WelcomeUser;

}

child.MaximumLength = maxChar;

base.MenuControl.UseShortId = true;

base.MenuControl.Controls.Add(child);

The PostCacheSubstitutionText control will prevent the username from being cached on the server as part of output cache settings, so that if a user uses the Sign in as a Different User menu item, they will always see the current username instead of a cached one. You can play with the PostCacheSubstitutionTextType to change how the username is displayed.

In order to insert this text into our menu, I added a PlaceHolder control into the ASCX markup, and then added the PostCacheSubstitutionText control to the PlaceHolder’s controls collection in code-behind. I replced the John Doe text in the markup with this:

<a href="#" class="profile_btn">

    <span class="image"><asp:Image ID="imageProfilePicture" runat="server" Width="20px" Height="20px" /></span>

    <span class="name"><asp:PlaceHolder ID="placeHolderWelcomeName" runat="server"></asp:PlaceHolder></span>

    <span class="arrow"></span>

</a>

I then added the following lines to the PreRender event:

// Username

PostCacheSubstitutionText welcomeText = new PostCacheSubstitutionText();

welcomeText.TextType = PostCacheSubstitutionTextType.UserName;

placeHolderWelcomeName.Controls.Add(welcomeText);

    

Summary

In this post, we deconstructed the OOB welcome menu control, figured out how to get the user’s profile picture, and got the user’s display name into the menu.

Our ASCX markup so far is:

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>

<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>

<%@ Import Namespace="Microsoft.SharePoint" %> 

<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="CustomWelcomeMenuControl.ascx.cs" Inherits="CustomWelcomeMenu.ControlTemplates.CustomWelcomeMenu.CustomWelcomeMenuControl" %>

<div class="header">

    <img class="header-logo" src="/images/header_logo.png" alt="" width="169" height="78" />

    <div class="header-bar">

        <div class="profile_menu">

        <a href="#" class="profile_btn">

            <span class="image"><asp:Image ID="imageProfilePicture" runat="server" Width="20px" Height="20px" /></span>

            <span class="name"><asp:PlaceHolder ID="placeHolderWelcomeName" runat="server"></asp:PlaceHolder></span>

            <span class="arrow"></span>

        </a>

            <div class="profile_dropdown">

                <div class="dropdown_bkgrd">

                    <ul>

                        <li>Edit Profile</li> 

                        <li>My Site</li>

                        <li>Log Out</li>                        

                        <li>Sign in as a Different User</li>

                    </ul>

                </div>

            </div>

        </div>

    </div>

</div>

Our ASCX code-behind so far is:

using System;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using Microsoft.SharePoint;

using Microsoft.SharePoint.WebControls;

 

namespace CustomWelcomeMenu.ControlTemplates.CustomWelcomeMenu

{

    public partial class CustomWelcomeMenuControl : UserControl

    {

        protected void Page_PreRender(object sender, EventArgs e)

        {    

 

    

            // Username

            PostCacheSubstitutionText welcomeText = new PostCacheSubstitutionText();

            welcomeText.TextType = PostCacheSubstitutionTextType.UserName;

            placeHolderWelcomeName.Controls.Add(welcomeText);

 

            // Profile picture

            SPList userInfoList = SPContext.Current.Web.GetCatalog(SPListTemplateType.UserInformation);

            SPListItem userProfileItem = userInfoList.GetItemById(SPContext.Current.Web.CurrentUser.ID);

            if (userProfileItem["Picture"] == null || string.IsNullOrEmpty(userProfileItem["Picture"].ToString()))

            {

                // Use default picture (or replace with another)

                imageProfilePicture.ImageUrl = "/_layouts/images/PERSON.GIF";

            }

            else

            {

                SPFieldUrlValue value = new SPFieldUrlValue(userProfileItem["Picture"].ToString());

                imageProfilePicture.ImageUrl = value.Url;

            }

        }

    }

}

Next, check out Part 2, where we learn how to display links to My Site and My Profile.

3 comments on “Creating a Custom Welcome Menu for SharePoint Server 2010 – Part 1
  1. Hi Excellent article. I am also same kind of requirement. Can you please provide javascript and css files i.e Expading the menu.

  2. Pingback: HowTO: Customize WELCOME menu items « Working with SharePoint

Comments are closed.