Using Calculated Fields in CAML to Display Conditional Images
Came across a nice gem in the newsgroups that I thought I would share here. Someone had a choice field with three values: failed; pass; re-run; and wanted to display a red image for items in the list matching the failed value, green for pass, and yellow for re-run (oh yeah, can you see where this is going).
I pointed them immediately to Ian Morrish’s article here on conditional formatting using a DataView Web Part which works nicely for this. However Colin Gardner came up with a nice solution that used the RenderPattern tag in CAML for a list to do the job. Here’s his solution:
1. Edit the FieldTypes.xml file (make backups for safety) and look for the row definition for the calculated field type (search for <Field Name="TypeName" DisplayName="TypeName">Calculated</Field>).
2. Modify the deafult render pattern in the <FieldSwitch> statement so that it handles the values returned by a calculated file in such a way that will return you an image/icon/traffic light. You will see that the <FieldSwitch> statement handles Boolean, Number, Currency and DateTime field types but anything else falls through and is processed by the code in the <Default> tag which is: <Column HTMLEncode="TRUE" AutoHyperLink="TRUE" AutoNewLine="TRUE"/>
You need to replace this default rendering with you're own custom logic. In my implementation I replaced it with another complete switch statement like the one below:
<Switch>
<Expr>
<GetFileExtension><Column/></GetFileExtension>
</Expr>
<Case Value="giF">
<HTML><![CDATA[<IMG SRC="]]></HTML><Column HTMLEncode="TRUE"/><HTML>"</HTML>
</Case>
<Default>
<Column HTMLEncode="TRUE" AutoHyperLink="TRUE"
AutoNewLine="TRUE"/>
</Default>
</Switch>
In this example the the Switch <Expr> calles the GetFileExtension function which processes the value in the calculated field and tries to extract a file extension. You can then use a Case statement to render the value returned by the calculated field in a way that makes sense. In the example above - if the GetFileExtension returns the string "giF" then I process the value as an image and render it as an HTML <IMG> tag.
Note that I chose to take advantage of the fact that the comparison is case sensitive but the source url for the image is not. This means that if my calculated field returns a string that ends with ".gif" rather than ".giF" then it will slip through the case statement and be rendered as before i.e. not as an image.
Of course you can modify the above to handle jpeg or any other graphics format that WSS can render.
3. Save the modified FieldTypes.xml file.
4. Create a Caluclated field in your list in the standard way with a formula that checks the value of your Choice field and returns a URL (relative will work) to the appropriate graphic file making sure that it is a format that will be handled by the newly modified render pattern. Something like:
=IF(Choice="A","/imagepath/red.giF", IF(Choice="B", "/imagepath/yellow.giF", "/imagepath/green.giF"))
Now you can use the calculated field wherever you like.
This is pretty elegant and nice to do since a) you don’t need to create a DVWP and therefore unghost a page b) it uses CAML which is always cool and c) you can set up a list with this in it so anyone creating a new list of this type will get the results. RenderPattern is a pretty powerful little thing because basically you can do anything in it, including conditional logic.
NUnit test results stored in a SharePoint list anyone? Yeah, who needs Team Server Foundation when you do stuff like this.