Automatically inherit SharePoint web parts from page layouts to child pages

When building publishing site using SharePoint 2010 it’s quite common to have few web parts that will make it to every page (or close to every page) on the site. An example could be a custom secondary navigation which you may choose to make a web part to allow some configuration. This means you need to provision such web part on each and every page that requires it – right? Well, there is another solution. What you can do is to define your web part in a page layout module just like you would in a page. In MOSS this trick would ensure your web part will make it to every page that inherits your custom layout; not so in SharePoint 2010.

One solution to that is to define the web part in the page layout, and programmatically copy web parts from page layout to pages inheriting them. In my case I will demonstrate how to achieve this by a feature receiver inside a feature that will be activate in site template during site creation. This way every time the site is created and pages are provisioned – my feature receiver will copy web parts from page layout to those newly created pages.

Here is the body of my feature receiver:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    SPWeb web = properties.Feature.Parent as SPWeb;
    if (null != web)
    {
        PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(web);
        SPList pages = pubWeb.PagesList;
        foreach (SPListItem page in pages.Items)
        {
            PublishingPage pubPage = PublishingPage.GetPublishingPage(page);
            pubPage.CheckOut();
            Copy.(pubPage.Url, web, pubPage.ServerRelativeUrl, 
pubPage.ListItem.Web);
            pubPage.CheckIn("Webparts copied from page layout");
        }
    }
}
private void Copy.(string pageUrl, SPWeb pageWeb, 
string pageUrl, SPWeb pageWeb)
{
    SPWeb web = null;
    SPWeb web2 = null;
    SPpageWebPartManager pageWebPartManager = 
pageWeb.GetpageWebPartManager(pageUrl, PersonalizationScope.Shared);
    SPpageWebPartManager pageWebPartManager = 
pageWeb.GetpageWebPartManager(pageUrl, PersonalizationScope.Shared);
    web2 = pageWebPartManager.Web;
    web = pageWebPartManager.Web;
    SPLimitedWebPartCollection webParts = pageWebPartManager..;
    SPLimitedWebPartCollection parts2 = pageWebPartManager..;
    foreach (System.Web.UI.WebControls..WebPart part in webParts)
    {
        if (!part.IsClosed)
        {
            System.Web.UI.WebControls..WebPart webPart = parts2[part.ID];
            if (webPart == null)
            {
                string zoneID = pageWebPartManager.GetZoneID(part);
                pageWebPartManager.AddWebPart(part, zoneID, part.ZoneIndex);
            }
        }
    }
}

Now, it’s up to you if you activate this feature manually under each web, or automate it according to your scenario; one thing for sure – once the feature is active – your web parts will be copied to pages inheriting the layout they were defined.

Good Luck!

About the author: Yaroslav Pentsarskyy