PANVEGA’s Blog

DotNet Development, SharePoint Customizing, Silverlight, MS Infrastructure and other tips and tricks

Adding a Webpart into a MasterPage with a Feature

Posted by PANVEGA on January 16, 2009

The best practise, when you want to add a Webpart into a MasterPage is using a Delegate Control with a Feature.  I wanted to add a Content Query Webpart into my Masterpage Page headline with a Custom Delegate Control.  Note!  You can not add a Webpart Zone into a MasterPage just static Webparts!  Many of the controls used on default.master are loaded using the Delegate Control. These include global links such as My Site/My Links and the publishing console. So using this approach, customizing the publishing console is a simple matter of providing a replacement .ascx and creating a feature as described here!

Why using a Delegate Control?

Using the concept of a delegate control, you can take any control that exists in Sharepoint today or your own custom creations and place them on a sharepoint page such that they override the existing control at whatever scope you desire (individual site, site collection or farm) and yet require no recoding of the page(s) itself.  In previous Sharepoint versions, this involvded either customizing the pages one by one and/or creating a whole new site defintion. With the concept of delegate controls in Sharepoint 2007, its a handful of lines of code and its far more powerful.

On every Sharepoint deployment I have ever done, it has been requested that the search box be modified, either comsmetically or functionally.

Here is a short example:

<SharePoint:DelegateControl runat=”server”
ControlId=”SmallSearchInputBox”/>

The delegate control tag, the best I can deduce, does a lookup of the features on the site that will share the controlID value of “SmallSearchInputBox”. Out of the box, there is only 1 of these declared, in the feature called ContentLightup.

What you can do (as documented in the SDK) is create your own feature that uses this same controlID but refers to a different underlyling .ascx (custom control) file. The delegate control feature will then check the list of all controls with this same ID and use the one that has the lowest sequence number as declared in the <control> tag as part of another xml file in the feature

<!– using a sequence number LOWER than default of 100 so our custom control gets loaded –>

<Control
Id=”SmallSearchInputBox”
Sequence=”61″
Controlsrc=”~/_controltemplates/searcharea.ascx” mce_src=”~/_controltemplates/searcharea.ascx”>
</Control>

Only thing to note here at this stage is the ControlId attribute – the Feature we create will use this to substitute the real user/server control.

Thus by copying the original feature and lowering the sequence number and changing the Controlsrc attribute to point to your .ascx file, you will cause Sharepoint to dynamically change the control that <SharePoint:DelegateControl> tag produces on the page.

Read more about Delegate Controls in my previous post

A delegate control allows you to light up functionality on a site-by-site basis and provides the scope to add a single control that doesn’t take over the entire page. Delegate controls are stand-ins for the actual controls you want to incorporate when you’re building a master page or designing a page layout. Instead of adding that specific search functionality, for example, you can add a delegate control. During run time SharePoint swaps out the delegate control with the best control for the matching functionality, which will be discussed in more detail shortly.

Declarations in Sequence
When you create a delegate control in a feature part of a page, the declaration is a sequence number. The lower the sequence number attached to a control, the better the chance that the control will be used to replace the associated delegate control, and the best control is defined as the control that has the lowest sequence number. When SharePoint selects the control to replace the delegate control, it looks through the list of activated controls and selects the best control or controls. If the delegate control is set to not allow multiple controls—such as in a page header, for instance—then it selects the control defined with the lowest sequence number.

Steps how to achive  my topic of this post:

  1. You can create a feature.xml, control.xml and a manifest.xml for e.g.
  2. Go to your site and put your web part onto a page in a normal web part zone, configure it the way you want to appear
  3. Export the webpart
  4. Create a new feature and put the details from the exported web part into the Control element and specify the feature details (including scope):
  5. By using a feature scoped at ‘Web‘, I can effectively use a different page header for different areas of my site without requiring different templates or code. (Note I’ve not tested this extensively, but since the <Control> element can be used at scope Web, Site, WebApplication or Farm, this should be perfectly feasible.)
  6. By adding AllowMutiple=true to the declaration, you can make the Delegate Control load more than one user/server control.
  7. Actually you can put your webpart code into a UserControl ascx file and make a reference into the control.xml file. However in this particular example I had some ussues with the user control. Then I decided to put everything into the control.xml file and oh wonder it worked finally (see code sample below)
  8. Very important change the Namespace from the CQWP from http://schemas.microsoft.com/WebPart/v3 to http://schemas.microsoft.com/sharepoint
  9. Edit your master page and put in a delegate control that has a ControlID attribute that matches up with what is in your feature file
  10. Instead of using the few default Delegate Controls you can create your own Control with a unique ID  e.g. BannerID (see below)
  11. Turn on the feature and the web part will appear where the delegate control is

control.xml:

<?xml version=”1.0″ encoding=”utf-8″ ?>
<Elements xmlns=”http://schemas.microsoft.com/sharepoint/”&gt;
<Control ControlAssembly=”Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c”
Id=”BannerID” ControlClass=”Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart” Sequence=”91″
>
<Property Name=”GroupBy”/>
<Property Name=”GroupStyle”>DefaultHeader</Property>
<Property Name=”Description”>Use to display a dynamic view of content from your site on a web page</Property>
<Property Name=”Direction” >NotSet</Property>
<Property Name=”ViewContentTypeId”  />
<Property Name=”XslLink” />     etc.
<Property Name=”UseCopyUtil” >False</Property>
<Property Name=”Title” >My Custom Webpart</Property>
<Property Name=”ContentTypeName”  />
<Property Name=”ChromeState”>Normal</Property>
<Property Name=”ItemStyle” >BannerAD</Property>
<Property Name=”NoDefaultStyle”  />
<Property Name=”FilterValue3″  />
</Control>
</Elements>

Parameters can be passed to the control via the declaration on the page. To read these, the control’s implementation should walk up the control tree to get the values. An example would be:

    <SharePoint:DelegateControl runat=server

    ControlId=PageHeader MyParam=MyValue>

    </SharePoint:DelegateControl>

So you see the assembly and class attributes are put into the control node, and then all of the property tags are just copied and pasted from the external web part (make sure you remove the “type” attributes though, you don’t need them here – also I think I needed to change the tags from property to Property (uppercase “P”) so that it would be fine when it validated against the schema). So when I deploy that it will go and put a content query web part on the page for me. Obviously I didn’t put all the properties from that web part on here (thus the dots in the middle) but you get the idea.

Here you find a list of available SharePoint WebControls

Code snipped from the MasterPage Code:

<asp:ContentPlaceHolder id=”PlaceHolderSiteName” runat=”server”>
<TABLE cellSpacing=0 cellPadding=4 width=”100%” border=0>
<TBODY>
<TR vAlign=top>
<TD width=”100%”>Rotation Banner:<BR><BR>
<SharePoint:DelegateControl AllowMultipleControls=”true” ControlId=”BannerID”
Visible=”true” runat=”server”/>

</TD>
</TR>
</TBODY>
</TABLE>
</asp:ContentPlaceHolder>

What I do find to be very cool about this though is that it means my web part is now nicely tied to a feature, meaning that if we need to change the properties of the web part we can just update the feature and redeploy the WSP file, SharePoint will pick up the change when the application pool is recycled and the changes will appear to users – this makes the process of updating the web part so very very simple. Also it means if we don’t want it anymore we can just disable to feature and the web part will no longer display, no editing of the master page is required. If you are putting web parts or controls onto your master page then this is definitely something you should consider doing.

More Information:

http://msdn.microsoft.com/en-us/library/ms470880.aspx

http://msdn.microsoft.com/en-us/library/ms463169.aspx

http://www.u2u.info/Blogs/Patrick/Lists/Posts/Post.aspx?ID=1633

http://msdn.microsoft.com/en-us/library/aa830815.aspx

http://www.tech-archive.net/Archive/SharePoint/microsoft.public.sharepoint.portalserver.development/2007-10/msg00113.html

http://www.sharepointnutsandbolts.com/2007/06/using-delegate-control.html

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: