How to: Create a Custom Field Type and Field Control
This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.
To create a custom field type, you can extend a default Windows SharePoint Services field type by defining a custom field type and control for displaying the field, and then adding a field type definition to register the field type and its control. You can create a Class Library project that defines custom classes for the field type and the control, copy the DLL of your project to the global assembly cache (GAC), and then add an XML file containing a definition that references the DLL to Local_Drive:\\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\XML.
Field Types and Field Controls
Most field types that are defined in the Microsoft.SharePoint namespace are associated with field controls that are defined in the Microsoft.SharePoint.WebControls namespace. For example, the SPFieldText class, which defines the field type for a single line of text, is associated with the Microsoft.SharePoint.WebControls.TextField class, which is specifically designed to display an SPFieldText object. A field type defines the metadata that is specific to a field instance. A field control defines the logic and behavior for displaying data according to the three control modes used in SharePoint lists: New, Display, and Edit. For more information about the object model for field types and field controls, see Custom Field Types.
You define a field type class and its control by creating an assembly. You register the class and its assembly, and also specify metadata and display patterns, through an XML file written in Collaborative Application Markup Language Core Schemas.
Example
The following example defines a custom field for displaying company logos that derives from the SPFieldText class.
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports Microsoft.SharePoint
Imports Microsoft.SharePoint.WebControls
Imports System.Web.UI
Imports System.Web.UI.WebControls
Namespace MS.Samples.SharePoint.CustomFieldType
Public Class MyCompanyLogoField
Inherits SPFieldText
Public Sub New(fields As SPFieldCollection, fieldName As String)
MyBase.New(fields, fieldName)
End Sub 'New
Public Sub New(fields As SPFieldCollection, typeName As String, displayName As String)
MyBase.New(fields, typeName, displayName)
End Sub 'New
Public Overrides ReadOnly Property FieldRenderingControl() As BaseFieldControl
Get
Dim fieldControl = New CompanyLogoPickerFieldControl(Me)
fieldControl.FieldName = InternalName
Return fieldControl
End Get
End Property
End Class 'MyCompanyLogoField
End Namespace 'MS.Samples.SharePoint.CustomFieldType
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace MS.Samples.SharePoint.CustomFieldType
{
public class MyCompanyLogoField : SPFieldText
{
public MyCompanyLogoField(SPFieldCollection fields, string fieldName)
: base(fields, fieldName)
{}
public MyCompanyLogoField(SPFieldCollection fields, string typeName, string displayName)
: base(fields, typeName, displayName)
{}
public override BaseFieldControl FieldRenderingControl
{
get
{
BaseFieldControl fieldControl = new CompanyLogoPickerFieldControl(this);
fieldControl.FieldName = InternalName;
return fieldControl;
}
}
}
}
The example overrides the FieldRenderingControl property to call a custom CompanyLogoPickerFieldControl constructor that is defined in the next example.
Example
The following example defines a custom control for displaying the previous custom field. The example overrides the CreateChildControls method to define a table for displaying a drop-down ListBox and corresponding images for selecting company logos.
The example specifies a default image file, MyDefaultLogo.png, to use for company logos, but this can be any name or image file type that you prefer.
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports Microsoft.SharePoint
Imports Microsoft.SharePoint.WebControls
Imports System.Web.UI
Imports System.Web.UI.HtmlControls
Imports System.Web.UI.WebControls
Namespace MS.Samples.SharePoint.CustomFieldType
Public Class CompanyLogoPickerFieldControl
Inherits TextField
Private field As MyCompanyLogoField
Private listBox As ListBox
Private table As HtmlTable
Public Sub New(parentField As MyCompanyLogoField)
Me.field = parentField
Me.listBox = New ListBox()
End Sub 'New
Protected Overrides Sub OnInit(e As EventArgs)
MyBase.OnInit(e)
End Sub 'OnInit
Protected Overrides Sub CreateChildControls()
MyBase.CreateChildControls()
Me.table = New HtmlTable()
Dim row As New HtmlTableRow()
table.Rows.Add(row)
Dim cell As HtmlTableCell = Nothing
If Me.ControlMode = SPControlMode.Edit OrElse Me.ControlMode = SPControlMode.New Then
cell = New HtmlTableCell()
cell.ColSpan = 2
cell.Attributes("class") = "ms-formdescription"
cell.InnerText = "Choose a logo:"
row = New HtmlTableRow()
table.Rows.Add(row)
cell = New HtmlTableCell()
row.Cells.Add(cell)
' Create a list selector.
Me.listBox = New ListBox()
Me.listBox.Rows = 12
Dim site As SPSite = SPContext.GetContext(Me.Context).Site
Dim dataSource As New SPDataSource()
dataSource.List = site.RootWeb.Lists("Logos")
Me.listBox.DataSource = dataSource
Me.listBox.DataTextField = "Title"
Me.listBox.DataValueField = "Name"
Me.listBox.DataBind()
' Get the current value of the field.
Dim currentValue As String = CStr(Me.ItemFieldValue)
If Not (currentValue Is Nothing) AndAlso currentValue <> String.Empty Then
Me.listBox.SelectedValue = currentValue
ElseIf Me.listBox.Items.Count > 0 Then
Me.listBox.SelectedIndex = 0
End If
' Add the script which updates the preview image.
Me.listBox.Attributes("onchange") = "document.all.imgLogoPreview.src = '/logos/' + this.options[this.selectedIndex].value;"
cell.Controls.Add(Me.listBox)
row.Cells.Add(cell)
End If
cell = New HtmlTableCell()
Dim literalControl As New LiteralControl()
Dim logo As String = Nothing
Dim logoObject As Object = Me.ItemFieldValue
If Not (logoObject Is Nothing) Then
logo = CStr(logoObject)
End If
If logo Is Nothing OrElse logo = String.Empty Then
logo = "MyDefaultLogo.png"
End If
literalControl.Text = "<img id='imgLogoPreview' src='/logos/" + logo + "'></img>"
cell.Controls.Add(literalControl)
row.Cells.Add(cell)
MyBase.Controls.Add(table)
End Sub 'CreateChildControls
Public Overrides Sub UpdateFieldValueInItem()
Me.EnsureChildControls()
Try
Me.Value = Me.listBox.SelectedValue
Me.ItemFieldValue = Me.Value
Catch Else
End Try
End Sub 'UpdateFieldValueInItem
Protected Overrides Sub Render(output As HtmlTextWriter)
Me.table.RenderControl(output)
End Sub 'Render
End Class 'CompanyLogoPickerFieldControl
End Namespace 'MS.Samples.SharePoint.CustomFieldType
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
namespace MS.Samples.SharePoint.CustomFieldType
{
public class CompanyLogoPickerFieldControl : TextField
{
private MyCompanyLogoField field;
private ListBox listBox;
private HtmlTable table;
public CompanyLogoPickerFieldControl(MyCompanyLogoField parentField)
{
this.field = parentField;
this.listBox = new ListBox();
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
}
protected override void CreateChildControls()
{
base.CreateChildControls();
this.table = new HtmlTable();
HtmlTableRow row = new HtmlTableRow();
table.Rows.Add(row);
HtmlTableCell cell = null;
if (this.ControlMode == SPControlMode.Edit || this.ControlMode == SPControlMode.New)
{
cell = new HtmlTableCell();
cell.ColSpan = 2;
cell.Attributes["class"] = "ms-formdescription";
cell.InnerText = "Choose a logo:";
row = new HtmlTableRow();
table.Rows.Add(row);
cell = new HtmlTableCell();
row.Cells.Add(cell);
// Create a list selector.
this.listBox = new ListBox();
this.listBox.Rows = 12;
SPSite site = SPContext.GetContext(this.Context).Site;
SPDataSource dataSource = new SPDataSource();
dataSource.List = site.RootWeb.Lists["Logos"];
this.listBox.DataSource = dataSource;
this.listBox.DataTextField = "Title";
this.listBox.DataValueField = "Name";
this.listBox.DataBind();
// Get the current value of the field.
String currentValue = (String)this.ItemFieldValue;
if (currentValue != null && currentValue != String.Empty)
{
this.listBox.SelectedValue = currentValue;
}
else if (this.listBox.Items.Count > 0)
{
this.listBox.SelectedIndex = 0;
}
// Add the script which updates the preview image.
this.listBox.Attributes["onchange"] = "document.all.imgLogoPreview.src = '/logos/' + this.options[this.selectedIndex].value;";
cell.Controls.Add(this.listBox);
row.Cells.Add(cell);
}
cell = new HtmlTableCell();
LiteralControl literalControl = new LiteralControl();
String logo = null;
object logoObject = this.ItemFieldValue;
if (logoObject != null)
{
logo = (String)logoObject;
}
if (logo == null || logo == String.Empty)
{
logo = "MyDefaultLogo.png";
}
literalControl.Text = "<img id='imgLogoPreview' src='/logos/" + logo + "'></img>";
cell.Controls.Add(literalControl);
row.Cells.Add(cell);
base.Controls.Add(table);
}
public override void UpdateFieldValueInItem()
{
this.EnsureChildControls();
try
{
this.Value = this.listBox.SelectedValue;
this.ItemFieldValue = this.Value;
}
catch (Exception)
{
;
}
}
protected override void Render(HtmlTextWriter output)
{
this.table.RenderControl(output);
}
}
}
To create a custom field type and a custom field control
In Microsoft Visual Studio, click File, point to New, and then click Project.
In the New Project dialog box, select the language for your project in the Project Types box, select Class Library in the Templates box, type a name and location for building the project, and then click OK.
To add a reference to the Microsoft.SharePoint assembly, right-click the project in Solution Explorer, and on the .NET tab in the Add Reference dialog box, select Windows SharePoint Services, and then click OK.
To give your custom assembly a strong name when you build the project, right-click Properties in Solution Explorer, click Signing, select Sign the assembly, and specify a name for the strong name key file.
Double-click the default project .cs or .vb file in Solution Explorer, and add code such as in the first example to define a class for a custom field that extends a default Windows SharePoint Services field type.
Right-click the project in Solution Explorer, point to Add, and then click New Item.
Select Code File in the Add New Item dialog box, and then click Add.
In Solution Explorer double-click the new .cs or .vb file that you created in the previous step, and add code such as in the second example to define a control for displaying the custom field that extends a default Windows SharePoint Services field control.
Press CTRL+SHIFT+B to build the solution.
In Windows Explorer, drag the DLL from your project folder into the GAC.
Example
The following example registers the custom field type that is defined in the previous example.
<?xml version="1.0" encoding="utf-8" ?>
<FieldTypes>
<FieldType>
<Field Name="TypeName">MyCompanyLogoField</Field>
<Field Name="ParentType">Text</Field>
<Field Name="TypeDisplayName">My Company Logo</Field>
<Field Name="TypeShortDescription">My Company Logo</Field>
<Field Name="UserCreatable">TRUE</Field>
<Field Name="Sortable">TRUE</Field>
<Field Name="AllowBaseTypeRendering">TRUE</Field>
<Field Name="Filterable">TRUE</Field>
<Field Name="FieldTypeClass">MS.Samples.SharePoint.CustomFieldType.MyCompanyLogoField, MyExtendedFieldTypeControl1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=34b96198b6e14eee</Field>
<PropertySchema>
<Fields></Fields>
</PropertySchema>
<RenderPattern Name="DisplayPattern">
<HTML><![CDATA[<img style="zoom: 50%" src="/logos/]]></HTML>
<Column HTMLEncode="TRUE" />
<HTML><![CDATA[">]]></HTML>
</RenderPattern>
</FieldType>
</FieldTypes>
The RenderPattern Element (Field Types) element defines how to display the field in the All Items list view.
This file must be named in the format fldtypes*.xml (for example, fldtypes_customfield.xml) and placed in Local_Drive:\\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\XML so that Windows SharePoint Services merges the contents of your custom file with the default FLDTYPES.XML file.
For more information about the schema for a custom field type, see Custom Field Type Definition.
To register and test the example
In a text editor, create a CAML field type definition file in \TEMPLATE\XML that specifies the custom field type and control that you created in the previous procedure.
Add the CAML file to Local_Drive:\\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\XML.
At a command prompt, type iisreset to reset Internet Information Services (IIS).
In the root Web site of a site collection, create a picture library named "logos" to contain the image files to use for company logos.
In a view of the list to which you want to add the custom field type, click Settings, and then click Create Column.
On the Create Column page, add the field type to the view, which in the previous example is called My Company Logo.
Edit existing items or create items in the list to specify company logos, which are displayed in all three control modes and in the list view.
See Also
Tasks
Walkthrough: Creating a Custom Field Type