What’s in a RenderPattern?

I like to follow what’s going on on the SharePoint forums and one of the things I’ve noticed is that practically every day somebody starts a thread about RenderPatterns. Either they’ve created a custom field and they want to know how to use RenderPatterns or they’ve read through the documentation, have created a RenderPattern and it doesn’t do what they expect. I thought I’d spend a bit of time documenting my findings with regard to rendering of custom fields and in particular the elusive RenderPattern.

The Documentation

We’ll start with the MSDN documentation since anybody looking to build a custom field is probably already familiar with this: http://msdn.microsoft.com/en-us/library/aa544291.aspx

One of the key things to be aware of here is that whenever you’re displaying your data in a list, the only thing that matters is the DisplayPattern CAML. The documentation suggests that you can create a rendering template or even build your own rendering control but neither of these techniques works when displaying your data in a list. We’ll get into the reasons for that later, but I just thought I’d make that clear up front because I don’t think it’s obvious from the documentation.

The Field Definition

When creating a custom field you’ll define a field definition in a file called fldtypes_myfieldname.xml, It’ll probably look something like this:

<fieldtype>
    <field name="TypeName">TestTextField</field>
    <field name="ParentType">Text</field>
    <field name="InternalType">Text</field>
    <field name="TypeDisplayName">TestTextField</field>
    <field name="TypeShortDescription">Description for TestTextField</field>
    <field name="UserCreatable">TRUE</field>
    <field name="Sortable">TRUE</field>
    <field name="AllowBaseTypeRendering">TRUE</field>
    <field name="Filterable">TRUE</field>
    <field name="FieldTypeClass">SpFieldTest.TestTextField, SpFieldTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8af7048eb6ec79b4</field>
    <propertyschema>
        <fields>
            <field name="MyCustomProperty" hidden="TRUE" displayname="My Custom Property" type="Text">          
            <default>My Default</default>
            </field>
        </fields>
    </propertyschema>
    <renderpattern name="HeaderPattern">
        <property select="DisplayName" htmlencode="TRUE"></property>
        </renderpattern>
        <renderpattern name="DisplayPattern">
        <column />
    </renderpattern>
</fieldtype>

 

There are a few things to be aware of when creating field definitions:

  1. Setting the ParentType is optional, if you do set it then effectively your field inherits it’s rendering configuration from the parent type. So unless you override the RenderPatterns, the patterns from the parent will be used. (When it comes to programmatically manipulating the field via an inherited SPField object the ParentType doesn’t make any difference but we’ll cover that later)
  2. If you do set a parent type, it must be valid. If you enter a parent type that’s invalid your control won’t render in a list even if you include a valid DisplayPattern. (You can tell is that’s the problem because your field won’t display a header in the list either). Valid parent types can be found in fldtypes.xml and other files that are named fldtypes_<Whatever>.xml in the ….web server extensions\12\TEMPLATE\XML folder. The base field types include:
    Counter Text Note Choice MultiChoice
    GridChoice Integer Number ModStat Currency
    DateTime Lookup Boolean Threading ThreadIndex
    Guid Computed File Attachments User
    URL Calculated Recurrence CrossProjectLink ContentTypeId
    MultiColumn LookupMulti UserMulti WorkflowStatus AllDayEvent
    WorkflowEventType PageSeparator
  3. If you don’t set a parent type you must include a HeaderPattern. If you don’t you’ll see something like this (not sure if the message is localised):

    image

  4. If you don’t specify a parent type, you must specify an InternalType. Valid values for InternalType are the same as those for ParentType. You can specify both ParentType and InternalType, but InternalType is ignored if ParentType is set. If you don’t specify either you’ll get an System.Runtime.InteropServices.COMException: Exception occurred. (Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION)) message.
  5. Neither ParentType nor InternalType are case sensitive.

 

The SPField Object

If you’re creating a custom field you’ll have created a new object that’s derived directly or indirectly from SPField. The documentation covering this object and how it all works is pretty good so I don’t have much to add except one important thing:

The parsing of a RenderPattern does not use your SPField object. It doesn’t matter what you override you’ll never get a debugger to stop in your object when rendering a list view because SPField isn’t used.

The RenderPattern

To properly understand the RenderPattern it’s worthwhile considering a bit of history. Back in the early days of SharePoint, Xslt wasn’t what it is today and so the good folks at Microsoft came up with CAML as an xml-based means of formatting data for SharePoint. Back then SharePoint Team Services didn’t have the whistles and bells that it does today but one of the things it did do was display custom data in a list on a web page and it did that by parsing the CAML definitions for each field. Today this behaviour is implemented by the SPList object’s RenderAsHtml method.

As you’ll see from the documentation(and probably know from bitter experience!), the actual mechanism behind RenderAsHtml isn’t apparent. The problem with this lack of information is that we have no way to know exactly how the CAML in our RenderPattern will be processed.

Here’s what I’ve been able to figure out by performing some black box testing:

  • Behind the scenes the RenderAsHtml method calls owssvr.dll?Cmd=RenderView
  • The way in which CAML is parsed is dependent on the type of field you’ve created. By type I’m referring to ParentType/InternalType in your field definition not the type of your SPField-based object. Certain CAML elements such as <LookupColumn> only work properly if your field is of type “Lookup” for example.
  • The properties that are available via the <Property> element vary depending on the type. I’ve been unable to find out which properties are available for each type. I suspect this is hard coded inside owssvr.dll.
  • The property type in your field definition governs the base SPField type that your custom field will be cast to when using the new or edit form. (So if you set the type to Lookup in your field definition but actually derive your custom field from SPFieldText, you’ll see an error when you try to edit or add)

 

Conclusion

RenderPatterns are old school, in fact they’re so old school that I suspect there’s no decent documentation because the folks that wrote the code behind it have all retired! Unfortunately we’re stuck with them in SharePoint 2007 and by the looks of it in SharePoint 2010 as well. So what can be done to give us back the control we need?

Edit 2 Feb 2010: SharePoint 2010, although it still supports the use of the ListViewWebPart and the underlying CAML madness, by default, when the UI is in v4 mode all lists are rendered using XSLT.

By default all lists and document libraries are rendered using the ListVieWebPart, this makes use of the problematic functionality described above. Thankfully, it doesn’t have to be this way. One easy way to get back control is to replace the ListViewWebPart with a DataFormWebPart.

You can easily do that in SharePoint Designer by navigating to your list, opening the aspx page that stores your view, right clicking on the ListViewWebPart and selecting the Convert to XSLT Data View option:

image

 

Hopefully this post gives a bit more detail on rendering for custom fields and saves you some time wading through the documentation on to find that the answer isn’t there. As always, comments/complaints/criticisms and questions are always welcome.

 

Edit 2 Feb 2010: Added a bit more info on a separate post - http://www.chaholl.com/archive/2010/02/02/disentangling-render-patterns.aspx

posted @ Saturday, November 07, 2009 4:32 PM

Print

Comments on this entry:

# re: What’s in a RenderPattern?

Left by nallayeldrab at 11/23/2009 5:09 PM
Gravatar
Thanks for this, eventually tripped over it... :-)

I have an open msdn forum topic:
social.msdn.microsoft.com/.../c9178653-75db-4b6...

which describes why I would be interested in this. Perhaps you may want to add your views or advice.

Good post though, been stressing about why my logic in methods such as:
GetFieldValueAsText(object value) on my Custom field are never called...
Just to confirm, and it appears to me to be true, doesn't matter what the base object extension is, the methods won't be called - I tried SPField and SPFieldText.

# re: What’s in a RenderPattern?

Left by chaholl at 11/23/2009 7:44 PM
Gravatar
Yep, it doesn't matter what type of SPField you implement, when it comes to rendering data in a list, you'll never use it. The code the generates the standard list view lives in a separate assembly and doesn't communicate with the .Net elements of SharePoint at all. THey bother share the same configuration and data source (SQL Server) but other than that they operate independently.

# re: What’s in a RenderPattern?

Left by Maciej Samoraj at 1/4/2010 2:05 PM
Gravatar
Hello Charlie !, your article was really helpfull for me, but anyway im still stuck with my custom multichoice filed. I have my ParentType set to MultiChoice, when field is attached to a list then column filter for this list contains only (all) and (empty) options. As i know column filter menu is a iframe to Filter.aspx which contains dropdown which is created using RenderAsHtml method. What can be wrong in here ?. I've tested query from Filter.aspx using u2u tool and is ok, im really stuck with this. PLEASE HELP !!

S.O.S and happy new year.

# re: What’s in a RenderPattern?

Left by Maciej Samoraj at 1/6/2010 9:07 AM
Gravatar
Ok, probably i know what is wrong, HeaderTemplate of MultiChoice generates filter dropdown based on the schema ( hardcoded values). But there is a MutliLookup where values are pupulated from the list. when im looking on the HeaderTemplate of Multichoice, and LookupMulti - they are almost the same (except sorting). i cannot find where this dropdown is filled in with values, there is only FieldFilterOptions tag. Is there any way to write custom HeaderTemplate with custom values populated from the list ?

# re: What’s in a RenderPattern?

Left by chaholl at 1/8/2010 11:16 AM
Gravatar
What were you hoping to customise about the list?

I doubt you'll be able to do it using CAML. I haven't tried it personally but I'd imagine that the renderpattern for the header template simply hooks up some script to the header. The script then calls filter.aspx, and filter.aspx does the work. You can see this happening by reviewing the querystring thats passed to filter.aspx.

I think your best bet, and this is a fair bit of work, is to create a custom replacement for filter.aspx that does what you want it do do. Then add some javascript to your page to change what happens when your header is clicked.

# re: What’s in a RenderPattern?

Left by maciej.samoraj at 1/9/2010 5:16 PM
Gravatar
hello chaholl, thanks for your answer. i did so, i added my extra code to filter.aspx and is working well now !

# re: What’s in a RenderPattern?

Left by spguy at 1/28/2010 4:59 PM
Gravatar
Hi Chaholl, thank you for the post.
I want to create a SPUrlField which takes a javascript function that I can set using a property (programatically, when I create the List, in my Code). And render the onclick="MyJavascriptFunctionSetProgramatically()" likie this:
<a href=xyz oncick=MyJavascriptFunctionSetProgramatically'myparam)>abc
So that when I click on the hyperlink in my list the javascript could get executed.

I created a FieldControl etc but the CreateChildControls() method is not getting called at all, when I put a breakpoint. If that doesnt work ?
Is it imperative that I should use a .ascx file ControlTemplate and have a HyperLink webcontrol there ?
Nothing seems to be working.
Anyhelp to get his working would be great.

Thank you.

# re: What’s in a RenderPattern?

Left by spguy at 1/28/2010 5:35 PM
Gravatar
Hi Charlie, thank you for the post.
I want to create a SPUrlField which takes a javascript function that I can set using a property (programatically, when I create the List, in my Code). And render the onclick="MyJavascriptFunctionSetProgramatically()" likie this:
<a href=xyz oncick=MyJavascriptFunctionSetProgramatically'myparam)>abc
So that when I click on the hyperlink in my list the javascript could get executed.

I created a FieldControl etc but the CreateChildControls() method is not getting called at all, when I put a breakpoint. If that doesnt work ?
Is it imperative that I should use a .ascx file ControlTemplate and have a HyperLink webcontrol there ?
Nothing seems to be working.
Anyhelp to get his working would be great.

Thank you.

# re: What’s in a RenderPattern?

Left by Charlie at 1/28/2010 6:43 PM
Gravatar
I don't think it'll be possible to parameterize the url on the list view. Maybe theres something that can be done in the list Schema.xml file to allow you to customize it on a list by list basis?

I'll have a mess around with it and post my findings

# re: What’s in a RenderPattern?

Left by Charlie at 1/28/2010 8:08 PM
Gravatar
Right, here's how you do it (I'll prepare a proper post on this when I've got a bit more time):

In schema.xml for your list, you'll see that you've got a load of Field elements in the Fields section. You can add attributes to these Field elements that can then be picked up by the render pattern for your custom field. So if you add an attribute called "ScriptToCall" then you can change your render pattern to pick up this value using <Property Select="ScriptToCall"/> and build up an appropriate anchor tag to display in the list view.

You with me?

If you need more detail please feel free to post.

# re: What’s in a RenderPattern?

Left by Charlie at 1/28/2010 8:18 PM
Gravatar
Also, forgot to mention - in response to your question about using a custom .ascx - it won't make any difference when it comes to rendering your field in a list. A custom .ascx is only used on the edit/new/display forms,

# re: What’s in a RenderPattern?

Left by SPguy at 1/29/2010 8:51 AM
Gravatar
Hi Charlie,
Thank you for the input but as I am new here I need more info.
So does that mean that we need to build a CustomSpFieldUrl and use the list's SchemaXML property to get the schemaxml and then modify it ?
I am not all that clear on it, more info would really help me.
Here is what I am trying. I creted a new MySPFieldURL extending from SPFieldURL and overriding the constructors but doing nothing. There is a Method called : "public override string GetValidatedString(object value)"
I am overriding it and without much validation I am returning it. Because on the SPFieldURLValue's URL property if I set the value as : "javascript:myfuction(myparam)", then it says "Invlid URL". So I am just overriding it. Have the fieldtype_MySpFieldUrl.xml wil be same as what it is for SPFieldURLexcept for the Class/Assembly.
Idea is to render the element like this : title

I did everything, but when I try to add MySPFieldURL to the fields then it throws an Object reference not set to an object exception.
After I create my MySPFieldUrl class, how to I use it ? Yes, I am GACing my dll etc. Copying the FieldType_MySPFieldURL.xml to the right place.
What do you think about this approach ?

Please let me know.

# re: What’s in a RenderPattern?

Left by SpGuy at 1/30/2010 3:46 PM
Gravatar
Hi Charlie,
I tried my approach and failed. I could get through the Invalid URl exception but later on, it gave out an exception - value not in the expected range as there is another validation that occurs somewhere in the unmanaged-layer of Sharepoint. So clearly that is not an option.
I tried your approach and went through the RenderPatterns of SPFieldURL and saw that we are able to set the width and height of the Image dynamically when used in the Image-Format (SPFieldURL). Now the point is how do I set the Widht or Height or in our case the "ScriptToCall" property.
As I mentioned, I want to set it in the OnItemAdded event of the SPList.
Someone was also suggesting that we could use SPFieldMultiColumn and render whatever we want usign the .ascx.
But if we are able to set the "ScriptToCall" dynamically this seems to be a better choice for me.

Please suggest me. Thank you in advance.

# re: What’s in a RenderPattern?

Left by SpGuy at 2/1/2010 4:22 PM
Gravatar
Hi Charlie,
I could change the RenderPattern and got onclick=myjavascript working and I am using the PageUrl and ServerUrl to get the items.
I am still trying to set the CustomProperty. I create the "ScriptToCall" property in the PropertiesSchema and tried to set a value from the C# code after creating my custom field. I am doing a SetCustomProperty("ScriptToCall", "myjavascript());
But the problem is the <Property Select="ScriptToCall" /> is coming out as empty when the field is rendered. I am doing a "Quick Watch" in debugmode and did a GetCutomProperty on the field to see if the SetCustomProperty(..) is sucessful and I am able to see it there.
But when I use in the RenderPattern its coming out as empty. Why ?
How do I set such properties ?
If I get this out I am all set.
Thank you in advance for your help.

# re: What’s in a RenderPattern?

Left by Charlie at 2/1/2010 4:27 PM
Gravatar
You need to change the schema.xml file that defines your list. The properties are defined as attributes on the field element.

I'll prepare a post on this tomorrow that covers it in more detail.

# re: What’s in a RenderPattern?

Left by Charlie at 2/2/2010 9:55 AM
Gravatar
Added another post with more info on how render patterns are used:

www.chaholl.com/.../...ngling-render-patterns.aspx

This doesn't specifically address your problem with rendering javascript but hopefully it'll explain how you can attach the name of the javascript to the field element and then pick it up in the render pattern.

Your comment:



 (will not be displayed)


 
 
 
Please add 6 and 3 and type the answer here:
 

Live Comment Preview: