Michael's profileMike HackerBlogLists Tools Help

Blog


    21 October

    Using a Control Adapter for Branding – Part 2

    In part 1 I described why a developer might choose to use a control adapter for branding out of the box SharePoint web parts.  In part 2 I will explain how to create a control adapter and how you can deploy it to work with SharePoint.   In part 3 I will show an easier way for integrating control adapters into your SharePoint environment.

    A control adapter allows a developers to change the default rendering behavior of any control.  In the case of SharePoint we can use the control adapter to modify how all or specific out of the box web parts are rendered.  This allows us to easily apply custom classes, styles and tags to the rendered output so we can control the branding of those web parts.

    The branding that I wanted to accomplish was to have all 4 corners of the web parts rounded and put styles in place to complete the intended effect.   The final branding of the web parts can be seen on the public website I recently completed called Destination Oakland.   The inside pages of the site are SharePoint publishing pages with a primary content publishing zone in the left and web parts along the right side.  This is where you will see the control adapter in action.

    To create a control adapter we start with a .NET class that inherits from the System.Web.UI.Adapters.ControlAdapter base class.   We then override the Render method to modify the HTML that will be generated by the controls which are associated to the control adapter.

    Below is an example control adapter used on the public SharePoint web site www.destinationoakland.com.    

    public class BrandingAdapter : ControlAdapter
        {
            protected override void Render(System.Web.UI.HtmlTextWriter writer)
            {
                var webpart = Control as WebPart;
                webpart.ChromeType = PartChromeType.None;
    
                StringWriter stringWriter = new StringWriter();
                using (HtmlTextWriter html = new HtmlTextWriter(stringWriter))
                {
                    base.Render(html);
                }
    
                //Start new table to format rounded corners.
                HtmlTable tblBranding = new HtmlTable();
                tblBranding.CellSpacing = 0;
                tblBranding.CellPadding = 0;
                tblBranding.Style.Add("width", "100%");
    
                #region Header
                HtmlTableRow trHeader = new HtmlTableRow();
                HtmlTableCell tcTopLeftCorner = new HtmlTableCell();
                tcTopLeftCorner.Style.Add("width", "6px");
                Image imgTopLeftCorner = new Image();
                imgTopLeftCorner.ImageUrl = Helper.GetSubPageImageURL(HttpContext.Current, "subheaderleft.png",true);
                tcTopLeftCorner.Controls.Add(imgTopLeftCorner);
                trHeader.Cells.Add(tcTopLeftCorner);
    
                HtmlTableCell tcTopCenter = new HtmlTableCell();
                tcTopCenter.Style.Add("background-image", Helper.GetSubPageImageURL(HttpContext.Current, "subheaderfill.png",false));
                tcTopCenter.Style.Add("background-repeat", "repeat-x");
                tcTopCenter.Controls.Add(new LiteralControl("<div class='destoak-webpartTitleArea'>" + webpart.Title + "</div>"));
                trHeader.Cells.Add(tcTopCenter);
    
                HtmlTableCell tcTopRightCorner = new HtmlTableCell();
                tcTopRightCorner.Style.Add("width", "6px");
                Image imgTopRightCorner = new Image();
                imgTopRightCorner.ImageUrl = Helper.GetSubPageImageURL(HttpContext.Current, "subheaderright.png",true);
                tcTopRightCorner.Controls.Add(imgTopRightCorner);
                trHeader.Cells.Add(tcTopRightCorner);
    
                tblBranding.Rows.Add(trHeader);
                #endregion
    
                #region Content
                HtmlTableRow trContent = new HtmlTableRow();
                HtmlTableCell tcContentLeft = new HtmlTableCell();
                tcContentLeft.Style.Add("background-image", Helper.GetTransparentImageURL(HttpContext.Current,"/_layouts/images/DestinationOakland/subpages/contentLeftShadow.png"));
                tcContentLeft.Style.Add("background-repeat", "repeat:y");
                trContent.Cells.Add(tcContentLeft);
    
                HtmlTableCell tcContentCenter = new HtmlTableCell();
                tcContentCenter.Style.Add("background-image", "/_layouts/images/DestinationOakland/subpages/contentFill.png");
                tcContentCenter.Style.Add("background-repeat", "repeat");
                tcContentCenter.Controls.Add(new LiteralControl("<div class='destoak-webpartBodyArea'>" + stringWriter.ToString() + "</div>"));
                trContent.Cells.Add(tcContentCenter);
    
                HtmlTableCell tcContentRight = new HtmlTableCell();
                tcContentRight.Style.Add("background-image", Helper.GetTransparentImageURL(HttpContext.Current,"/_layouts/images/DestinationOakland/subpages/contentRightShadow.png"));
                tcContentRight.Style.Add("background-repeat", "repeat:y");
                trContent.Cells.Add(tcContentRight);
    
                tblBranding.Rows.Add(trContent);
                #endregion
    
                #region Footer
                HtmlTableRow trFooter = new HtmlTableRow();
                HtmlTableCell tcBottomLeftCorner = new HtmlTableCell();
                tcBottomLeftCorner.Style.Add("width", "6px");
                Image imgBottomLeftCorner = new Image();
                imgBottomLeftCorner.ImageUrl = Helper.GetTransparentImageURL(HttpContext.Current,"/_layouts/images/DestinationOakland/subpages/contentleftcorner.png");
                tcBottomLeftCorner.Controls.Add(imgBottomLeftCorner);
                trFooter.Cells.Add(tcBottomLeftCorner);
    
                HtmlTableCell tcBottomCenter = new HtmlTableCell();
                tcBottomCenter.Style.Add("background-image", Helper.GetTransparentImageURL(HttpContext.Current,"/_layouts/images/DestinationOakland/subpages/contentbottomshadow.png"));
                tcBottomCenter.Style.Add("background-repeat", "repeat:x");
                trFooter.Cells.Add(tcBottomCenter);
    
                HtmlTableCell tcBottomRightCorner = new HtmlTableCell();
                tcBottomRightCorner.Style.Add("width", "6px");
                Image imgBottomRightCorner = new Image();
                imgBottomRightCorner.ImageUrl = Helper.GetTransparentImageURL(HttpContext.Current,"/_layouts/images/DestinationOakland/subpages/contentrightcorner.png");
                tcBottomRightCorner.Controls.Add(imgBottomRightCorner);
                trFooter.Cells.Add(tcBottomRightCorner);
    
                tblBranding.Rows.Add(trFooter);
                #endregion
    
                writer.Write("<div class='destoak-webpartTable'>");
                tblBranding.RenderControl(writer);
                writer.Write("</div>");
    
            }
        }
    

     

    It is recommended that you build and deploy the control adapter as part of your SharePoint branding WSP installer.  For testing purposes you can manually deploy the assembly to your web front ends global assembly cache.

    One last thing must be accomplished before the control adapter will work.  You need to add a browser file to the App_Browsers folder for your specific IIS SharePoint web application.  (Remember to do this on ALL web front end servers)   This file tells IIS to apply a control adapter to a specific control type while rendering the web page.   For example I may indicate that all Microsoft.SharePoint.WebPartPages.ContentEditorWebPart controls are rendered using my custom branding ControlAdapter. 

    By default SharePoint 2007 has a browser file called compat.browser located in the App_Browsers folder.  You could modify that file or you can create your own file that ends with the extension of .browser and place it in the App_Browsers folder.   Below is the contents of an example .browser file.  You will need to modify it to reference your specific control adapter class name and the control you wish to brand.

    <browsers>
       <browser refID=”Default”>
          <controlAdapters>
                <adapter controlType=”Microsoft.SharePoint.WebPartPages.ContentEditorWebPart”
                         adapterType=”MyNamespace.MyControlAdapter” />
           </controlAdapters>
       </browser>
    </browsers>

    One drawback about this method is that it is not easy to create and deploy a .browser file to all of the SharePoint web front end servers via a .WSP installer.  In part 3 of this series I will show you how to hook up a control adapter via code in the web sites masterpage.   This will simplify the process of using control adapters within SharePoint.

    Comments

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    Trackbacks

    Weblogs that reference this entry
    • None