We got a request for a project to mimic the Workspace column of an Event Item, in that sense that they also wanted an icon in the header and an icon for the link value instead of the text. The site column, ‘Workspace’, and site content type, ‘Event’, are hidden in SharePoint. Besides that, the ‘Workspace’ column is of the ‘Cross Project Link’ field type, which isn’t available. This field type cannot be used via the user interface. Since we got two additional requirements, open link in new window and display description besides icon, we opted to inherit from the parent type ‘URL’. Via the user interface, this is the ‘Hyperlink or Picture’ type. For maximum reuse, we build a new field type with some custom properties and header and display pattern.
First we defined the field type and called it an ‘Imagelink’. We also associated a field type class which we will define later.
<Field Name="TypeName">Imagelink</Field> <Field Name="TypeDisplayName">Image with Url</Field> <Field Name="TypeShortDescription">Imagelink</Field> <Field Name="ParentType">URL</Field> <Field Name="UserCreatable">TRUE</Field> <Field Name="ShowInListCreate">TRUE</Field> <Field Name="ShowInSurveyCreate">FALSE</Field> <Field Name="ShowInDocumentLibraryCreate">TRUE</Field> <Field Name="ShowInColumnTemplateCreate">TRUE</Field> <Field Name="FieldTypeClass">Imagelink.Imagelink, Imagelink, …</Field>
Next we had to define some custom properties to store the image links and additional requirements (default values were set to images inside SharePoint out-of-the-box).
<PropertySchema> <Fields> <Field Name="HeaderImage" DisplayName="Header Image" Hidden="FALSE" Type="Text"> <Default>/_layouts/images/linktosite.gif</Default> </Field> <Field Name="ItemImage" DisplayName="Item Image" Hidden="FALSE" Type="Text"> <Default>/_layouts/images/linktosite.gif</Default> </Field> <Field Name="ShowDescription" DisplayName="Show description" Hidden="FALSE" Type="Boolean"></Field> <Field Name="OpenLinkInNewWindow" DisplayName="Open link in new window" Hidden="FALSE" Type="Boolean"></Field> </Fields> </PropertySchema>
To finish the ‘fldTypes_…’ xml file, we must implement the HeaderPattern and DisplayPattern.
The header pattern is pretty straight forward. If the HeaderImage custom property is not defined or empty, use the textual name of the field. In the other case, we build a HTML image tag and set the source and title attribute of this field.
<RenderPattern Name="HeaderPattern" DisplayName="HeaderPattern"> <Switch> <Expr><Property Select="HeaderImage" /></Expr> <Case Value=""> <Property Select="DisplayName" HTMLEncode="TRUE" /> </Case> <Default> <HTML><![CDATA[<img src="]]></HTML> <Property Select="HeaderImage" /> <HTML><![CDATA[" title="]]></HTML> <Property Select="DisplayName" HTMLEncode="TRUE" /> <HTML><![CDATA[" />]]></HTML> </Default> </Switch> </RenderPattern>
The display pattern is a bit more complex, since we have to readout the values of several custom properties. There are multiple switch statements:
1. Check the value of the field (line 3), if empty display nothing and exit, else continue 2. If value of the custom property ‘ItemImage’ (line 7) is empty 2.1. Open the HTML Hyperlink opening tag and set the href attribute 2.2. Check the value of the custom property ‘OpenLinkInNewWindow’ (line 13-15) 2.2.1. If true, add an extra attribute target and set it to _blank 2.3. Close the HTML Hyperlink opening tag 2.4. Print the description 2.5. Print the HTML Hyperlink closing tag 3. If value of the custom property ‘ItemImage’ (line 7) is not empty 3.1. If value of the custom property ‘ShowDescription’ (line 26-28) is true 3.1.1. Open the HTML Hyperlink opening tag and set the href attribute 3.1.2. Check the value of the custom property ‘OpenLinkInNewWindow’ (line 34-36) 3.1.2.1. If true, add an extra attribute target and set it to _blank 3.1.3. Close the HTML Hyperlink opening tag 3.1.4. Print the HTML Image tag and set border, style, source and title attribute 3.1.5. Print the HTML Hyperlink closing tag 3.1.6. Open a second HTML Hyperlink opening tag and set the href attribute 3.1.7. Check the value of the custom property ‘OpenLinkInNewWindow’ (line 50-52) 3.1.7.1. If true, add an extra attribute target and set it to _blank 3.1.8. Close the HTML Hyperlink opening tag 3.1.9. Print the HTML Hyperlink closing tag 3.2. If value of the custom property ‘ShowDescription’ (line 26-28) is false 3.2.1. Open the HTML Hyperlink opening tag and set the href attribute 3.2.2. Check the value of the custom property ‘OpenLinkInNewWindow’ (line 66-68) 3.2.2.1. If true, add an extra attribute target and set it to _blank 3.2.3. Close the HTML Hyperlink opening tag 3.2.4. Print the HTML Image tag and set border, source and title attribute 3.2.5. Print the HTML Hyperlink closing tag
<RenderPattern Name="DisplayPattern" DisplayName="DisplayPattern"> <Switch> <Expr><Column /></Expr> <Case Value=""></Case> <Default> <Switch> <Expr><Property Select="ItemImage" /></Expr> <Case Value=""> <HTML><![CDATA[<a href="]]></HTML> <Column HTMLEncode="TRUE" /> <HTML><![CDATA["]]></HTML> <Switch> <Expr> <Property Select="OpenLinkInNewWindow" /> </Expr> <Case Value="True"> <HTML><![CDATA[ target="_blank"]]></HTML> </Case> </Switch> <HTML><![CDATA[>]]></HTML> <Column2 HTMLEncode="TRUE" /> <HTML><![CDATA[</a>]]></HTML> </Case> <Default> <Switch> <Expr> <Property Select="ShowDescription" /> </Expr> <Case Value="True"> <HTML><![CDATA[<a href="]]></HTML> <Column HTMLEncode="TRUE" /> <HTML><![CDATA["]]></HTML> <Switch> <Expr> <Property Select="OpenLinkInNewWindow" /> </Expr> <Case Value="True"> <HTML><![CDATA[ target="_blank"]]></HTML> </Case> </Switch> <HTML><![CDATA[><img border="0" style="margin-right:5px;" src="]]></HTML> <Property Select="ItemImage" /> <HTML><![CDATA[" title="]]></HTML> <Column2 HTMLEncode="TRUE" /> <HTML><![CDATA["></a>]]></HTML> <HTML><![CDATA[<a href="]]></HTML> <Column HTMLEncode="TRUE" /> <HTML><![CDATA["]]></HTML> <Switch> <Expr> <Property Select="OpenLinkInNewWindow" /> </Expr> <Case Value="True"> <HTML><![CDATA[ target="_blank"]]></HTML> </Case> </Switch> <HTML><![CDATA[>]]></HTML> <Column2 HTMLEncode="TRUE" /> <HTML><![CDATA[</a>]]></HTML> </Case> <Default> <HTML><![CDATA[<a href="]]></HTML> <Column HTMLEncode="TRUE" /> <HTML><![CDATA["]]></HTML> <Switch> <Expr> <Property Select="OpenLinkInNewWindow" /> </Expr> <Case Value="True"> <HTML><![CDATA[ target="_blank"]]></HTML> </Case> </Switch> <HTML><![CDATA[><img border="0" src="]]></HTML> <Property Select="ItemImage" /> <HTML><![CDATA[" title="]]></HTML> <Column2 HTMLEncode="TRUE" /> <HTML><![CDATA["></a>]]></HTML> </Default> </Switch> </Default> </Switch> </Default> </Switch> </RenderPattern>
Finally we have to implement the fieldtypeclass by overriding the SPFieldUrl class. Define a private Boolean IsInitialized and set it false. The constructors are straight forward, as is the FieldRenderingControl. For the GetFieldValueAsHtml, you have to return the Url of the SPFieldUrlValue. In the OnAdded and OnUpdated method, check the IsInitialized Boolean and if not true, call the following method.
Private Sub ConfigureSchemaXml() IsInitialized = Not IsInitialized Dim HeaderImageValue As String = _ MyBase.GetCustomProperty("HeaderImage") Dim ItemImageValue As String = _ MyBase.GetCustomProperty("ItemImage") Dim ShowDescriptionValue As Boolean = _ MyBase.GetCustomProperty("ShowDescription") Dim OpenLinkInNewWindowValue As Boolean = _ MyBase.GetCustomProperty("OpenLinkInNewWindow") Dim doc As XmlDocument = New XmlDocument() doc.LoadXml(MyBase.SchemaXml) If (doc.FirstChild.Attributes("HeaderImage") Is Nothing) Then Dim xmlAttrib As XmlAttribute = doc.CreateAttribute("HeaderImage") xmlAttrib.Value = HeaderImageValue doc.FirstChild.Attributes.Append(xmlAttrib) Else doc.FirstChild.Attributes("HeaderImage").Value = HeaderImageValue End If If (doc.FirstChild.Attributes("ItemImage") Is Nothing) Then Dim xmlAttrib As XmlAttribute = doc.CreateAttribute("ItemImage") xmlAttrib.Value = ItemImageValue doc.FirstChild.Attributes.Append(xmlAttrib) Else doc.FirstChild.Attributes("ItemImage").Value = ItemImageValue End If If (doc.FirstChild.Attributes("ShowDescription") Is Nothing) Then Dim xmlAttrib As XmlAttribute = doc.CreateAttribute("ShowDescription") xmlAttrib.Value = ShowDescriptionValue doc.FirstChild.Attributes.Append(xmlAttrib) Else doc.FirstChild.Attributes("ShowDescription").Value = _ ShowDescriptionValue End If If (doc.FirstChild.Attributes("OpenLinkInNewWindow") Is Nothing) Then Dim xmlAttrib As XmlAttribute = _ doc.CreateAttribute("OpenLinkInNewWindow") xmlAttrib.Value = OpenLinkInNewWindowValue doc.FirstChild.Attributes.Append(xmlAttrib) Else doc.FirstChild.Attributes("OpenLinkInNewWindow").Value = _ OpenLinkInNewWindowValue End If MyBase.SchemaXml = doc.OuterXml End Sub
If everything went well, you should see a new fieldtype, but it cannot be used from the userinterface. You will still get some errors. However if you use it from code, it will work already. In Part 2, I will discuss how to alter this one to use it as a real fieldtype via the userinterface.
January 21, 2010 at 15:58
[...] Snyckers under SharePoint | Tags: Custom Field Editor, SPField | Leave a Comment In ‘Mimicking the Workspace column of an Event Item (Part 1)‘, I noted that it would not work if you use the custom field type from the UI. After some [...]