Community Pick: Many members of our community have endorsed this article.

How to create and deploy a custom field type within Sharepoint

Published:
Updated:
This example will use a custom field type to create a drop down list populated from a Sharepoint List.

There are four main components to building a custom field&

"      Field Class* This must inherit from an existing SPField class. e.g. SPFieldText. It handles custom validation for the field, as well as defining the Field Control used to display it.
"      User Control Rendering Template.  This defines the control to be used to display the custom field.
"      Field Control Class. This contains the code-behind for the user control file, and defines how the control is rendered.
"      Field Type Definition File. This contains the information that SharePoint needs to correctly render the field, as well as information about the assembly that contains the compiled field type.

The example demonstrates a custom field type designed to list all entries within an example list entitled Organisation List.
 

1. Field Class



Each instance of this class represents a separate field based on the custom field type. It must inherit from one of the SPField subtypes, a list of which can be found at the end of this document. The most commonly used subtype is SPFieldText, and this is used in the following example code.

using System;
                      using System.Runtime.InteropServices;
                      using System.Security.Permissions;
                      
                      using Microsoft.SharePoint;
                      using Microsoft.SharePoint.WebControls;
                      using Microsoft.SharePoint.Security;
                      
                      namespace Company.Application.Controls
                      {
                          [CLSCompliant(false)]
                          [Guid("01d5cd28-741b-4229-8d47-24e5a068b5af")]
                          public class OrganisationDropDownField : SPFieldText
                          {
                              public OrganisationDropDownField(SPFieldCollection fields, string fieldName)
                                  : base(fields, fieldName)
                              {
                              }
                              
                              public OrganisationDropDownField(SPFieldCollection fields, string typeName, string displayName)
                                  : base(fields, typeName, displayName)
                              {
                              }
                      
                              public override BaseFieldControl FieldRenderingControl
                              {
                                  [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
                                  get
                                  {
                                      BaseFieldControl fieldControl = new OrganisationDropDownFieldControl();
                                      fieldControl.FieldName = this.InternalName;
                      
                                      return fieldControl;
                                  }
                              }
                      
                              public override string GetValidatedString(object value)
                              {
                                  if (Required && String.IsNullOrEmpty(value.ToString()))
                                  {
                                      throw new SPFieldValidationException("No Organisation selected");
                                  }
                                  return base.GetValidatedString(value);
                              }
                          }
                      }
                      

Open in new window



Here the BaseFieldControl is set to use a custom drop down control called OrganisationDropDownFieldC ontrol, defined in the Field Control Class below. In the example some custom validation is also included within the overridden GetValidatedString method, to ensure a value is selected when mandatory.

2. User Control Rendering Template



In order to render the drop down control, a user control is required, consisting of an XML rendering template and a code behind file.

The rendering templated is defined within an .ascx file, and in the example is little more than an asp dropdownlist control, as follows:

<%@ Control Language="C#" %>
                      <%@ 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="OrganisationDropDownFieldControl" runat="server">
                        <Template>
                          <asp:DropDownList ID="OrganisationSelector" runat="server" />
                        </Template>
                      </SharePoint:RenderingTemplate> 
                      

Open in new window


The ID of the rendering template element matches the name of the code behind class for this user control, while the ID of the drop down list matches the name of the DropDownList property within the control class.

3. Field Control Class



The field control class is the code behind file for the rendering template, and is compiled alongside the Field Class in the same assembly. It is this class that is used to populate the drop down list with its data, as well as handling the current value.

using System;
                      using System.Runtime.InteropServices;
                      using System.Web.UI.WebControls;
                      
                      using Microsoft.SharePoint;
                      using Microsoft.SharePoint.WebControls;
                      
                      namespace Company.Application.Controls
                      {
                          [CLSCompliant(false)]
                          [Guid("dfbce0dc-3215-4352-b65f-25a83e8b427b")]
                          public class OrganisationDropDownFieldControl : BaseFieldControl
                          {
                              protected DropDownList OrganisationSelector;
                      
                              protected override string DefaultTemplateName
                              {
                                  get
                                  {
                                      return "OrganisationDropDownFieldControl";
                                  }
                              }
                      
                              public override object Value
                              {
                                  get
                                  {
                                      EnsureChildControls();
                                      return OrganisationSelector.SelectedValue;
                                  }
                                  set
                                  {
                                      EnsureChildControls();
                                      OrganisationSelector.SelectedValue = (string)this.ItemFieldValue;
                                  }
                              }
                      
                              protected override void CreateChildControls()
                              {
                                  if (Field == null || ControlMode == SPControlMode.Display)
                                      return;
                      
                                  base.CreateChildControls();
                      
                                  OrganisationSelector = (DropDownList)TemplateContainer.FindControl("OrganisationSelector");
                      
                                  if (OrganisationSelector == null)
                                  {
                                      throw new ApplicationException("Error: Cannot load .ascx file");
                                  }
                      
                                  if (OrganisationSelector.Items.Count == 0)
                                  {
                                      if (SPContext.Current.Site != null)
                                      {
                                          SPList orgList = SPContext.Current.Site.RootWeb.Lists["Organisations List"];
                                          if (orgList == null)
                                          {
                                              throw new ApplicationException("Organisations List not found");
                                          }
                      
                                          OrganisationSelector.Items.Add(String.Empty);
                                          foreach (SPItem org in orgList.Items)
                                          {
                                              if (org["Title"] == null)
                                              {
                                                  continue;
                                              }
                                              string orgTitle = org["Title"].ToString();
                                              OrganisationSelector.Items.Add(new ListItem(orgTitle, orgTitle));
                                          }
                                      }
                                  }
                              }
                          }
                      }
                      

Open in new window


The class must inherit from BaseFieldControl (or one of the classes in Windows SharePoint Services that derive from it), and be modified as follows:

"      Include a .Net control within its properties of the desired type, with a name matching the ID of the corresponding control within the template. The example field includes a DropDownList control called OrganisationSelector.
"      Override the DefaultTemplateName property with the name of rendering template
"      Override the value property to enable the getting and setting of the current value of the control.
"      Override the CreateChildControls method to populate the control. For the example control, this is where the drop down list is populated with values from the Organisations List.

This class must be compiled into the same assembly as the Field Class.
 

4. Field Type Definition File



The final requirement for the custom control is a field type definition file, which holds the metadata behind the field itself.

<?xml version="1.0" encoding="utf-8" ?>
                      <FieldTypes>
                        <FieldType>
                          <Field Name="TypeName">OrganisationDropDownField</Field>
                          <Field Name="ParentType">Text</Field>
                          <Field Name="TypeDisplayName">Organisation</Field>
                          <Field Name="TypeShortDescription">Organisation</Field>
                          <Field Name="UserCreatable">TRUE</Field>
                          <Field Name="ShowInListCreate">TRUE</Field>
                          <Field Name="ShowInSurveyCreate">TRUE</Field>
                          <Field Name="ShowInDocumentLibraryCreate">TRUE</Field>
                          <Field Name="ShowInColumnTemplateCreate">TRUE</Field>
                          <Field Name="SQLType">ntext</Field>
                          <Field Name="FieldTypeClass">Company.Application.Controls.OrganisationDropDownField, Company.Application.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7389d5f4596c3c69 </Field>
                          <RenderPattern Name="DisplayPattern">
                            <Switch>
                              <Expr>
                                <Column/>
                              </Expr>
                              <Case Value="">
                              </Case>
                              <Default>
                              </Default>
                            </Switch>
                          </RenderPattern>
                        </FieldType>
                      </FieldTypes>
                      

Open in new window



The TypeName element must match the name of the field control, while ParentType must match the SPField subtype used within the Field Class. Note the FieldTypeClass element that must match the name of the Field Class itself, along with its assembly details.
 

5. Deploying the custom field types



The Field Class and Field Control Class must be compiled into a signed assembly, which must be placed in the GAC ( a custom field binary cannot be installed into the Application bin directory).
In order to have the relevant files deployed automatically by the solution, the rendering template and field type definition file must be added to the VS project using the same folder path as will be used by SharePoint.
Therefore, add a new folder under the VS project with a name of 12. Below that, add another folder called Template and within that add two more folders: ControlTemplates and XML. Place the rendering template in the ControlTemplates folder, and add the field type definition file to the XML folder.
Next add a manifest.xml file that will tell sharepoint where to deploy the individual components, as follows:

<Solution xmlns="http://schemas.microsoft.com/sharepoint/" SolutionId="F3A12E2E-31EF-478d-AC2A-E389704F281E">
                        <Assemblies>
                          <Assembly Location="Company.Application.Controls.dll" DeploymentTarget="GlobalAssemblyCache">
                          </Assembly>
                        </Assemblies>
                        <TemplateFiles>
                          <TemplateFile Location="XML\fldtypes_OrganisationField.xml" />
                          <TemplateFile Location="ControlTemplates\OrganisationFieldControl.ascx" />
                        </TemplateFiles>
                      </Solution>
                      

Open in new window


Note the Assembly element that holds the name of the dll, with a DeploymentTarget of the GAC. The Template files entry will place the rendering template and field definition files in their relevant locations within the sharepoint hierarchy
Because the assembly has been placed in the GAC, it will need to be manually added to the SafeControls section of each application using the control.
<SafeControl Assembly="Company.Application.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7389d5f4596c3c69", Namespace="Company.Application.Controls" TypeName="*" Safe="True" />
                      

Open in new window




 
Finally add a definition file to automatically include all relevant files into a .wsp SharePoint solution package.

;WSP CAB Generation
                      .Set DiskDirectoryTemplate=CDROM
                      .Set CompressionType=MSZIP
                      .Set UniqueFiles=Off
                      .Set Cabinet=On
                      
                      Manifest.xml
                      %assembly%
                      
                      .Set DestinationDir="XML"
                      12\Template\XML\fldtypes_OrganisationField.xml
                      
                      .Set DestinationDir="ControlTemplates"
                      12\Template\ControlTemplates\OrganisationFieldControl.ascx
                      

Open in new window


This package can then be deployed using the STSADM utility.
SPField subtypes

"      Microsoft.SharePoint.SPFie ldAttachme nts    
"      Microsoft.SharePoint.SPFie ldBoolean    
"      Microsoft.SharePoint.SPFie ldCalculat ed    
"      Microsoft.SharePoint.SPFie ldComputed    
"      Microsoft.SharePoint.SPFie ldCrossPro jectLink    
"      Microsoft.SharePoint.SPFie ldDateTime    
"      Microsoft.SharePoint.SPFie ldFile    
"      Microsoft.SharePoint.SPFie ldLookup    
"      Microsoft.SharePoint.SPFie ldMultiCho ice    
"      Microsoft.SharePoint.SPFie ldMultiCol umn    
"      Microsoft.SharePoint.SPFie ldMultiLin eText    
"      Microsoft.SharePoint.SPFie ldNumber    
"      Microsoft.SharePoint.SPFie ldPageSepa rator    
"      Microsoft.SharePoint.SPFie ldRecurren ce    
"      Microsoft.SharePoint.SPFie ldText    
"      Microsoft.SharePoint.SPFie ldUrl

1
12,782 Views

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.