I love rendering templates when I first came across them in WSS3 in 2008, when I started with SP 2007, I was still on 2003 until then, I thought they were brilliant it gave me a way of managing the display of a form and controlling the look and feel based in specific SharePoint groups as I could choose what fields were shown or not.

 

But the one thing I do remember is they are a bitch! to get right.  With no ability to debug those initial steps and the poor logging, even in verbose mode, going on these past two days I’ve been trying to recreate the process have been painful.

 

Luckily I found a great blog post on creating Rendering Templates that covered the basics, a lot of which I remembered but its still nice to have a guide.

    http://www.3guysonsharepoint.com/?p=987

Even with this guide there are some additional things I picked up that might help when you have a go.

 

  1. Rendering Templates live in the ROOT of CONTROLTEMPLATES folder, they wont work anywhere else so don’t even bother trying.
  2. Rendering templates, whilst they look and act a bit like ASCXs they ain’t fully, so don’t try and do any code behind in the template (this can be done in other proper user controls).
  3. Some guides show just the template in their examples, YOU NEED all the @assembly @register and @control stuff, in the guide mentioned look for the last bit of code that says "so your full template will look like this" they mean it, you need all the extra bits
  4. When it doesn’t work it just displays a blank page.
  5. ULS logs help, a tiny bit, in that it tells you it didn’t load the template

When starting off, Start VERY simple, dont bother to try and do anything fancy, just make sure your basic rendering template and registration of it are correct.

A minimum Rendering template is this, minus the @ stuff at the top (go nick this from DefaultTemplates.acx) ,this is 2007 code BTW.

<SharePoint:RenderingTemplate ID="BinaryJamListForm" runat="server">
<Template>    
    <span id=’part1′>            
    Hi         
    </span>
</Template>
</SharePoint:RenderingTemplate>

*Wire that up, see the 3guys guide above on doing that.

 

When that is done you can create a new custom user control, this is also covered in the 3guys guide but again some additional information

 

  1. Remember when developing this, you cant just copy to Hive and gac it, you need the SAFECONTROLS entry (the guide didnt mention this, probably too much 2010 dev).
  2. If it is in the GAC there is something about ascx I only learned today, when you have the @Control entry in the page you have to fully qualify the Inherits attribute, OR if you have an @Assembly reference to it instead it has to GO ABOVE THE @CONTROL reference, this got be big time, 10 yrs of coding user controls and I only just found this out.

    thx to http://blog.zebsadiq.com/post/SharePoint-Could-not-load-type-error.aspx, for setting me on the right path here, by telling me about the Control needing to be fully qualified its this that made me think my Assembly reference needed to be above, once moved my stuff worked.

Some interesting bits about creating a user control that replaces the rendering template.

This is the minimum needed to replicate the default (minus @ statments at the top)

<SharePoint:InformationBar ID="InformationBar1" runat="server" />
<SharePoint:FormToolBar ID="FormToolBar1" runat="server" />
<table class="ms-formtable" style="margin-top: 8px;" border="0" cellpadding="0"    cellspacing="0"     width="100%">    
<tr>        
    <td nowrap="nowrap" valign="top" width="190px" class="ms-formlabel">            
       <h3 class="ms-standardheader">                Title3 <span class="ms-formvalidation">*</span>             </h3>         </td>        
        <SharePoint:ListFieldIterator ID="ListFieldIterator1" runat="server" />         
        <SharePoint:FormComponent ID="FormComponent2" TemplateName="AttachmentRows" runat="server" />
</table>
<table cellpadding="0" cellspacing="0" width="100%">    
<tr>        
<td class="ms-formline">            
     <img src="/_layouts/images/blank.gif" width="1" height="1" alt="" /></td>     </tr> </table>
<table cellpadding="0" cellspacing="0" width="100%" style="padding-top: 7px">    
<tr>        
   <td width="100%">            
       <SharePoint:ItemHiddenVersion ID="ItemHiddenVersion1" runat="server" />                
       <SharePoint:ParentInformationField ID="ParentInformationField1" runat="server" />           
       <SharePoint:InitContentType ID="InitContentType1" runat="server" />                
       <wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbl" RightButtonSeparator="&nbsp;"                 runat="server">                
           <template_buttons>
                <SharePoint:CreatedModifiedInfo ID="CreatedModifiedInfo1" runat="server"/>  
            </template_buttons>                
            <template_rightbuttons>
              <SharePoint:SaveButton runat="server"/>
              <SharePoint:GoBackButton runat="server"/>
           </template_rightbuttons>            
        </wssuc:ToolBar>        
    </td>    
</tr>
</table>
 

 

It’s the Control

      <SharePoint:ListFieldIterator ID="ListFieldIterator1" runat="server" />

that does all the magic and it has some great properties you should explore, hiding fields, what mode am I in.  If you choose to put your on fields on the form then If they are placed above the Field terator then the Iterator will not show them again.  If you want your custom version below the Field Iterator then add yours to the excludefields property and then add it underneath.

Or alternatively you could take full control of the form and do your own thing for eery field, but then of course new fields will not be added to your custom for.

There are different types of field iterator, I think Survey has its own.  Or you could inherit and create your own of course.

This is the default example of how to add your own field, imagine this block immediately above the FieldIterator.

 

<tr>        
   <td nowrap="nowrap" valign="top" width="190px" class="ms-formlabel">            
      <h3 class="ms-standardheader">Title3 <span class="ms-formvalidation">*</span></h3>          
   </td>        
<td valign="top" class="ms-formbody" width="400px">            
     <SharePoint:FormField ID="FormFieldTitle3" TabIndex="1" FieldName="Title3" runat="server"  />            
     <SharePoint:FieldDescription FieldName="Title3" ID="FieldDescription3" runat="server" />            
     <SharePoint:AppendOnlyHistory FieldName="Title3" ID="AppendOnlyHistory3" runat="server" />        
   </td>    
</tr>

 

Of course you can add custom validators here and jQuery etc.

If your custom form needs to set values that it looks up and is not on the Form then you will have to override the SAVE button and user your own.  Inherit from    Microsoft.SharePoint.WebControls.SaveButton.  This is a post in it’s own right so I’ll skip this bit.

In your event Save Clicked on your inherited Save Button then you have to set the list item values this is done like this

   SPContext.Current.ListItem["Description"] = myLookedUpValue;

Nothing else to do the base classes handle the rest of the save.

 

Lastly every guide discusses how you can wire up the template using list defs and content type defs and feature activations on a Content type.

BUT, you can simply edit the Form pages in SharePoint Designer, Look at the ListFormWebPart, it has a property <TemplateName>  this can be set (at least in 2007 ) to your custom rendering template.

Obviously the best way of doing this is to attach to a content type, but if like me you are having to back fit something someone else creating its a handy option to have, hope it still works in 2010, to property is still listed so fingers crossed.

Advertisements