Cloning The SharePoint Toolbar for Custom Web Parts

Trying to match the “SharePoint look” is always a challenge for developers. Recently I had to build a web part that would live along side other “stock” SharePoint web parts. I also needed a functional toolbar for the web part and having it on the same page I wanted a seamless look to the toolbar so it looked just like any other part of the solution.

In the past I would just create a lot of HTML helpers to spit out the right markup with my values dropped in. I wanted something a little more elegant so I turned to my best programming buddy, the Internet. Doing a little sleuthing I found a path that I would take. First I found this MSDN article on creating a custom field control. Snuggled inside the code sample was a snippet of code to create a custom toolbar inherited from the RepeatedControls class which would mimic the look and feel of a SharePoint toolbar. Buried in the comments for the RepeatedControls class I found a link to Reza Alirezaei’s blog entry where he implemented this (his previous attempt used the ITemplate interface but had issues with bin deployments and FBA based websites).

His code and the code snippet on the MSDN article gave me enough ammo to pursue my attempt. When I first implemented what Reza had done, I was a little disappointed. It wasn’t *quite* a match to the SharePoint one and didn’t support adding separators or buttons without images. The problem is that Reza’s code uses DIV elements and while I prefer this over the TABLE approach, SharePoint 2007 is full of TABLEs (and tables inside of tables inside of tables…). So I set off to do a few modifications.

Here’s the original SharePoint toolbar for a typical list item that you see on the DispForm.aspx page:

SharePointToolbar

The code modifications I did were really minor so kudos to Reza for digging out this nugget in the first place as you can’t easily find out how to do this on MSDN. The changes were mostly around using TABLE tags instead of DIVs, aligning images to the middle of the table row, and adding the appropriate classes and styles. Also this is somewhat improved over the stock SharePoint output in that the IMG tags are closed correctly. I’m not sure if it validates against W3C (what SharePoint code does?) but it gives me a bit of a warm and fuzzy.

public class FileToolbar : RepeatedControls
{
    // {0} = Button text
    // {1} = Button link
    // {2} = Tooltip text
    // {3} = Button image source
    private const string ButtonImageHtmlFormat = @"                                        
    <td id=""_spFocusHere"" class=""ms-toolbar"" noWrap=""nowrap"">
        <table cellSpacing=""0"" cellPadding=""1"">
            <tr>
                <td class=""ms-toolbar"" noWrap=""nowrap"">
                    <a class=""ms-toolbar"" title=""{2}"" href=""{1}"">
                        <img style=""border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; 
                            border-left-width: 0px"" align=""absMiddle"" alt=""{2}"" src=""{3}"" 
                            border=""0"" width=""16"" height=""16"" /img>
                    </a>
                </td>
                <td class=""ms-toolbar"" noWrap=""nowrap"">
                    <a class=""ms-toolbar"" href=\""{1}"" title=""{2}"">{0}</a>
                </td>
            </tr>
        </table>
    </td>";
</span><span style="color: #008000;">//</span><span style="color: #008000;"> {0} = Button text
</span><span style="color: #008000;">//</span><span style="color: #008000;"> {1} = Button link
</span><span style="color: #008000;">//</span><span style="color: #008000;"> {2} = Tooltip text</span><span style="color: #008000;">

private const string ButtonHtmlFormat = @" <td id=""_spFocusHere"" class=""ms-toolbar"" noWrap=""nowrap""> <table cellSpacing=""0"" cellPadding=""1""> <tr> <td class=""ms-toolbar"" noWrap=""nowrap""> <a class=""ms-toolbar"" href=""{1}"" title=""{2}"">{0}</a> </td> </tr> </table> </td>";

</span><span style="color: #008000;">//</span><span style="color: #008000;"> {0} = Separator text/image source</span><span style="color: #008000;">

private const string SeparatorHtmlFormat = @" <td class=""ms-separator""> {0} </td>";

</span><span style="color: #0000FF;">public</span><span style="color: #000000;"> FileToolbar()
{
    HeaderHtml </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">@"</span><span style="color: #800000;">
        &lt;table class=""ms-toolbar"" width=""100%"" 
        border=""0"" cellSpacing=""0"" cellPadding=""2""&gt;&lt;tr&gt;</span><span style="color: #800000;">"</span><span style="color: #000000;">;
    FooterHtml </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">@"</span><span style="color: #800000;">
        &lt;td class=""ms-toolbar"" width=""99%"" nowrap&gt;
            &lt;img alt="""" src=""/_layouts/images/blank.gif"" 
                width=""1"" height=""18""/&gt;
        &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</span><span style="color: #800000;">"</span><span style="color: #000000;">;
}

</span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> AddButton(</span><span style="color: #0000FF;">string</span><span style="color: #000000;"> buttonId, </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> buttonText, </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> clientOnClick, </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> tooltipText,
                      </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> buttonImageSrc)
{
    var buttonMarkupLiteral </span><span style="color: #000000;">=</span><span style="color: #000000;">
        </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Literal
            {
                Text </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">string</span><span style="color: #000000;">.Format(
                    </span><span style="color: #0000FF;">string</span><span style="color: #000000;">.IsNullOrEmpty(buttonImageSrc) </span><span style="color: #000000;">?</span><span style="color: #000000;"> ButtonHtmlFormat : ButtonImageHtmlFormat,
                    SPHttpUtility.HtmlEncode(buttonText),
                    SPHttpUtility.HtmlEncode(clientOnClick),
                    SPHttpUtility.HtmlEncode(tooltipText),
                    SPHttpUtility.HtmlUrlAttributeEncode(buttonImageSrc)),
                ID </span><span style="color: #000000;">=</span><span style="color: #000000;"> buttonId
            };
    Controls.Add(buttonMarkupLiteral);
}

</span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> AddSeparator()
{
    var literal </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Literal {Text </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">string</span><span style="color: #000000;">.Format(SeparatorHtmlFormat, </span><span style="color: #800000;">"</span><span style="color: #800000;">|</span><span style="color: #800000;">"</span><span style="color: #000000;">)};
    Controls.Add(literal);
}

}

ButtonHtmlFormat is a formatting constant for buttons without images (the “Alert Me” button at the end), ButtonImageHtmlFormat is for regular buttons with images. The images must be 16x16 pixels in size. Try to re-use the stock SharePoint ones if you can so users are familiar with them. The worst thing is seeing a Save icon that’s different depending on what page you’re on.

You also might notice on the FooterHtml there’s an extra TD added with a blank image file set to 1px wide using up 99% of the space. This is to force all of the toolbar items to scrunch up (technical term) to the left. Without this, the elements will be spread out across the entire toolbar.

To use this, just create the toolbar class in your web part and add whatever buttons/separators you need:

private void CreateToolbar()
{
    var fileToolbar = new FileToolbar {ID = "ToolBar"};
    Controls.Add(fileToolbar);
    
    fileToolbar.AddButton("NewItem", "New Item", "NewForm.aspx", 
        "Click here to create a new item in this list.", "/_layouts/IMAGES/newitem.gif"); 
    fileToolbar.AddSeparator();
    fileToolbar.AddButton("EditItem", "Edit Item", "EditForm.aspx", 
        "Click here to edit this item.", "/_layouts/IMAGES/edititem.gif");
    fileToolbar.AddSeparator();
    fileToolbar.AddButton("DelItem", "Delete Item", "DeleteForm.aspx", 
        "Click here to delete this item.", "/_layout/IMAGES/delitem.gif");
    fileToolbar.AddSeparator();
    fileToolbar.AddButton("ManagePerm", "Manage Permissions", "ManagePermissions.aspx", 
        "Click here to manage permissions for this item.", "/_layouts/IMAGES/manageperm.gif");
    fileToolbar.AddSeparator();
    fileToolbar.AddButton("AlertMe", "Alert Me", "FormAlerts.aspx", 
        "Click here to create an alert for this item.", string.Empty);
}

Here’s the output from the code above.

CustomToolbar

The spacing is *slightly* off. I think this might be because there’s an additional (empty) A link added to the SharePoint output but for me this is good enough.

Enjoy!

2 Comments

Comments have been disabled for this content.