Building your first custom field type

Start by creating a new WSPBuilder project. You have WSPBuilder, right? Call it whatever you like, I’ve called mine SPMType. WSPBulder automatically creates a signing key and sets up your project to be signed.

Next, add a TEMPLATE folder under the 12 folder, and then an XML folder under the TEMPLATE folder.

Inside the XML folder, add a new XML file, called ‘fldtypes_SPMType.xml’. Or, choose another name, as long as you adhere to the fldtypes_XXXXXX.xml format.

Your solution explorer should now look like this:

Field Type Definition

Open the fldtypes_SPMType.xml file and add the following XML code. I’ll explain each element afterwards:

<?xml version=”1.0″ encoding=”utf-8″ ?>

<FieldTypes>

<FieldType>

<Field Name=”TypeName”>SPMType</Field>

<Field Name=”ParentType”>Text</Field>

<Field Name=”TypeDisplayName”>SPMType</Field>

<Field Name=”TypeShortDescription”>Description for SPMType</Field>

<Field Name=”UserCreatable”>TRUE</Field>

<Field Name=”Sortable”>TRUE</Field>

<Field Name=”AllowBaseTypeRendering”>TRUE</Field>

<Field Name=”Filterable”>TRUE</Field>

<Field Name=”FieldTypeClass”>[5-PART STRONG NAME]</Field>

</FieldType>

</FieldTypes>

You need to modify the FieldTypeClass element to insert the 5-part strong name of your field type class which we will create in a moment.

Each of the Field elements has a Name that is used to define the field type we are creating. The TypeNameis the internal name used when we create columns from this field type. In the site column we created above this would match the Type attribute, which in our example was Text.

The ParentType is also vital, as it defines one of several root types from which our custom field type will inherit. You must always inherit your custom field type from another field type.

The TypeDisplayName and the TypeShortDescription are only for your eyes’ enjoyment, you can enter whatever values you like here. the UserCreatable states if users should be able to create new columns from this type, while the Sortable and Filterable states if the columns created from this field type should be sortable and filterable, respectively.

The AllowBaseTypeRendering specifies whether the field type should fall back to its parent rendering in case of problems rendering the field type.

Now for that FieldTypeClass.

WSPBuilder will happily sign your assembly for you to create a strong-named assembly. However, this only produces the four-part strong name. We need to prefix this four-part name with the name of our class. Which class you ask? Ah, we get to that when we create the…

Field Type Class

First, make sure you have added a reference to the Microsoft.SharePoint.dll to your project.

In the solution explorer, add a new class file to the root of your project. Name it something like SPMFieldType.cs. If you like, put it in a folder, but in any case, open the .cs file and add the following code:

using System;

using System.Collections.Generic;

using System.Text;

using Microsoft.SharePoint;

namespace SPMType

{

public class SPMFieldType : SPFieldText

{

public SPMFieldType(SPFieldCollection fields, string fieldName)

: base(fields, fieldName)

{

}

public SPMFieldType(SPFieldCollection fields, string typeName, string displayName)

: base(fields, typeName, displayName)

{

}

}

}

One small thing first, before I forget. Let’s grab that five-part strong name we needed for the field type definition. First, build your solution, you may use the the WSPBuilder->Build WSP. Next, find the four-part strong name of your assembly. Finally, add the namespace.classname to the front of the strong name to create a five-part strong name. In my assembly this looks like this:

“SPMType.SPMFieldType, SPMType, Version=1.0.0.0, Culture=neutral, PublicKeyToken=817b2cbd5ec31d67”

Your PublicKeyToken will be different, as may your assembly, class, and namespace names.

Add this string to the FieldTypeClass element in your fldtypes_SPMType.xml field definition file.

Back to the class, we are inheriting from the SPFieldText class which makes sense since our parent type is Text. However, we are not bound by this, we can use any of the other SPFieldXXXX classes as the parent class for our own field type class.

Next we need to implement the constructors for our class, and SPFieldText determines the signatures for these constructors. For our class we don’t actually need to do anything but call the base constructor, but you can add functionality here to implement custom property handling or add other features as you see fit.

At this point we have actually created all we need to get our custom field type up and running. Of course, we’ve just created the most useless custom field type there is, as all we have done is implement the SPFieldText type, which is quite well done already by the built-in field type Text. However, we have a frame into which we can put a beautiful picture, so for now, just build (WSPBuilder->Build WSP) and deploy (WSPBuilder->Deploy) and sit back and wait. No need to activate anything, remember that custom field types are not deployed in features, so your field type will be available once the solution is deployed. Check this out in the Create new column of a list or when you go to create a new site column:

If you add a column based on your new field type, it will behave exactly like a regular Text type, since we haven’t really added anything ‘Custom’ yet. Let’s add custom to the equation now.

Custom Field Type Control

Our first order of business is to create a control class to act as the rendering control for our new field type.

Start by adding a reference to System.Web since we will now deal with creating web controls.

Continue by adding yet another class file to the root of your project, this time called ‘SPMFieldControl.cs’ or something along those lines. To that class, add the following code:

using System;

using System.Collections.Generic;

using System.Text;

using Microsoft.SharePoint;

using Microsoft.SharePoint.WebControls;

namespace SPMType

{

public class SPMFieldControl : BaseTextField

{

}

}

Note that we are inheriting from the BaseTextField class. Again, this is nothing extraordinary since we are creating a text class field type. However, for other field type classes you might want to inherit from another control.Here is a list of some of the Field controls from which we can inherit:

AllDayEventField

AttachmentsField

AttendeeField

BaseChoiceField

BaseTextField

BooleanField

CalculatedField

ComputedField

CrossProjectLinkField

DateTimeField

FieldValue

FileField

FormField

LookupField

ParentInformationField

RatingScaleField

RecurrenceField

UrlField

UserField

In addition, several of these, such as the BaseTextField have child types from which you also can inherit. The BaseTextField for example has BaseNumberField, NoteField, and TextField as child classes, and even more grand-children classes.

For our purposes, however, I really just want to show you the anatomy of a custom field type control, so we’ll base our control on the BaseTextField class.

First we must tell the control which template to use for rendering the control. We do this by overriding the DefaultTemplateName property as such:

protected override string DefaultTemplateName

{

get

{

return “TextField”;

}

}

The TextField is the default rendering template used for the single line of text field types we are mimicking. If you recall from Part 2 we looked at the DefaultTemplates.ascx file in the [12]\TEMPLATE\CONTROLTEMPLATES folder. This file also contains the TextField rendering template. This template is incredibly simple, but will do for the moment.

At this point our control behaves like the default single line of text. Let’s add something to make sure we’re doing things right. Let’s override the RenderFieldForDisplay method which is use to, well, Render Field For Display. Bet you didn’t see that coming…

Add the following override to your SPMFieldControl class:

protected override void RenderFieldForDisplay(System.Web.UI.HtmlTextWriter output)

{

output.Write(“Custom displaymode: “);

base.RenderFieldForDisplay(output);

}

Again we’re simply relying on the underlying BaseTextField to do most of the manual labor, however adding the “Custom displaymode: “ enables us to see that we are in fact modifying the rendering of the field.

I’ll show you some more advanced samples in a moment, but for now, let’s connect our new field type control to the field type we created earlier. To do this, go back to your SPMFieldType.cs file, and add the following override to your class:

public override Microsoft.SharePoint.WebControls.BaseFieldControl FieldRenderingControl

{

get

{

SPMFieldControl c = new SPMFieldControl();

c.FieldName = this.InternalName;

return c;

}

}

You might want to add a ‘using Microsoft.SharePoint.WebControls;’ statement by the way, but that’s just for prettier code.

This code instantiates an object of our new control class and assigns the FieldName of that object to the field type internal name.

Finally, build your WSP as described above and redeploy. You may need to do an IISRESET to get your changes updated.

Try creating a new column based on your field type on a list and then add a new item. You will notice that the new column behaves exactly like a text field

I bet by now you’re going: “Aw, come one, we haven’t seen any custom rendering at all, only mimicking of the default single line of text”. Patience, young Skywalker.

Add your new item and the display that item. Let’s see if your 1 second of patience has paid off:

Wohoo! Congratulations, you’ve just made… Well, absolutely nothing if you ask your boss, but hey, you made it yourself, right? That’s got to be worth something. Let’s see if we can impress your boss as well.

Oh, yeah, the date. I got a bit delayed writing this article.

One Step Further

Ok, so we have wired up our field type and we have connected that field type to a field control. We might as well utilize that to our advantage.

We want to create our own rendering template and not rely on the DefaultTemplates.ascx template. After all, we might want to add a nice Ajax control, or perhaps even a Silverlight control? No, I wont do that for you, that’s a completely different show, but I’ll show you how to create your own rendering template.

First, in your solution explorer, add a folder named CONTROLTEMPLATES to the TEMPLATE folder under the 12 folder.

Inside the CONTROLTEMPLATES folder, still in solution explorer, add a new Text file, and name it MyCoolTextBox.ascx. Using a text file but naming it .ascx makes Visual Studio recognize the file as a web user control even if this is not a web project.

Next, open the MyCoolTextBox.ascx and add the following outline:

<%@ Control %>

<%@ Assembly Name=”Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>

<%@ Register TagPrefix=”SharePoint” Assembly=”Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c”

Namespace=”Microsoft.SharePoint.WebControls” %>

<SharePoint:RenderingTemplate ID=”MyCoolTextBox” runat=”server”>

<Template>

</Template>

</SharePoint:RenderingTemplate>

Now, inside the Template tag, let your designers go bananas. Yes, I mean bananas, designers always love that. I’ll add one provision for now: Make sure you have an ASP:TextBox control with an Id of “TextField”. I’ll explain why in a moment. Besides that, do whatever you like.

Finally we need to tell our control to use the new rendering template. Go back into the SPMFieldControl and update the DefaultTemplateName override as such:

protected override string DefaultTemplateName

{

get

{

return “MyCoolTextBox”;

}

}

By the way, if you ever get the error ‘Corrupted control template. Please check RenderingTemplate of “TextField” in the control template ascx file.’ while working with the BaseTextField class, don’t bother checking your TextField template, as the name ‘TextField’ is hardcoded in the Microsoft.SharePoint.dll. I just spent two hours chasing after the wrong rendering template. Now you don’t have to.

Back to our fancy new rendering template. Before you go and deploy your new WSP, uninstall the old one using WSPBuilder->Uninstall. The reason is that by default WSPBuilder will upgrade your solution. Upgrading a solution does not add new files, and since we just added our new ascx control we need to make a clean install. After the uninstall completes, go ahead and deploy as normal.

Depending on what you decided to put inside the Template tag of your control you will see your changes when you refresh your Edit or New form. I’ve added

<asp:TextBox ID=”TextField” runat=”server” BackColor=”Cyan” BorderStyle=”None”></asp:TextBox>

to my control and get this:

For some reason I never got a job offer as a designer. Go figure, I think this looks beautiful.

Before I wrap up with some final thoughts and some further resources for you, I’d like to explain a bit of the magic that goes on here. You see, when we inherited our control class from the BaseTextField class we got a ton of free functionality. The BaseTextField searches for a TextBox control with an Id of “TextField” inside whatever renderingtemplate we send it. If the BaseTextField finds such a TextBox it gladly hooks up all the required functionality for us, including populating the TextBox with the right values when editing. This happens in the CreateChildControls() method of the BaseTextField class.

By not overriding the CreateChildControls() in our own class we basically get that functionality for free. See why having a TextBox with an Id of “TextField” makes sense now? Of course, you can override the CreateChildControls() if you want absolute and complete control over the building of your control, but I think it makes sense to let Microsoft work a bit for all the money we send them, and letting them handle as much of the nitty-gritty details as possible is at least sensible to me.