Wednesday, March 25, 2009

using AdditionalPageHead for emitting your controls to OOTB sharepoint master page

Delegate Controls in sharepoint has become one of the most loved additions in wss v3.
But if you dont want to replace any OOTB control, but just want to add you own control to the master page, 'AdditionalPageHead' comes to your rescue.

AdditionalPageHead is the only control which has 'AllowMultipleControls' attribute set to true.


SharePoint:DelegateControl runat="server" ControlId="AdditionalPageHead" AllowMultipleControls="true"/

but the problem is that this control is under page's head tag ...
We need to have our control inside body tag and at a specified location.

The solution lies in the fact that inside your control you can walk the Control tree of the page and move/add controls at the runtime.

1> Write a feature for your control
with element manifest as

Control
Id="AdditionalPageHead"
ControlAssembly="MyControls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a42ac00482be031f"
ControlClass="MyControls.MasterControl"/
2> inside your control, find the placeholder control and add your control to it

public class MasterControl : WebControl
{
protected override void CreateChildControls()
{
base.CreateChildControls();
addControls();
}
public void addControls()
{
try
{
//ControlsElement is my custom class that stores the details about the controls i want to the master page
foreach (ControlsElement c in ConfigCache.Controls)
{
try
{
Assembly asembly = Assembly.Load(c.Assembly);
if (null == asembly)
continue;
Type controlType = asembly.GetType(c.TypeName);
if (null == controlType)
continue;
Control control = Page.LoadControl(controlType, null);
//if not able to load the control, then move to next element
if (null == control)
continue;

//set the ControlID as the name
control.ID = c.Name;

//find the placeholder in the master page
Control placeholder = GetControl(this.Page, c.Placeholder); //Page.FindControl(c.Placeholder);
if (null != placeholder)
{
//if the place holder is found then add to the control to it
placeholder.Controls.Add(control);
}
}
catch (Exception)
{
//skip the current element
}
}
}
catch (Exception)
{
//throw ex;
}
}

}
Result: I have added a bunch of custom controls to the OOTB master page

Note : there are knows performance issues with using Delegate controls

link on placeholders in master pages:
http://sharepoint.microsoft.com/blogs/GetThePoint/Lists/Posts/Post.aspx?ID=115
http://msdn.microsoft.com/en-us/library/ms476046.aspx

Delegate controls:
http://msdn.microsoft.com/en-us/library/ms478826.aspx
http://www.codeproject.com/KB/sharepoint/sharepointdelegatecontrol.aspx