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

  1. In Microsoft Visual Studio, click File, point to New, and then click Project.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. Right-click the project in Solution Explorer, point to Add, and then click New Item.

  7. Select Code File in the Add New Item dialog box, and then click Add.

  8. 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.

  9. Press CTRL+SHIFT+B to build the solution.

  10. 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

  1. 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.

  2. Add the CAML file to Local_Drive:\\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\XML.

  3. At a command prompt, type iisreset to reset Internet Information Services (IIS).

  4. 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.

  5. In a view of the list to which you want to add the custom field type, click Settings, and then click Create Column.

  6. On the Create Column page, add the field type to the view, which in the previous example is called My Company Logo.

  7. 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

Concepts

Custom Field Types