Creating Custom Fields in Sharepoint


Sharepoint customization makes Sharepoint a real-world application where developers can customize fields the way they want. Using Sharepoint customization techniques, you can make all your columns and fields and make all your own logic comes true and working with Sharepoint.

There are many benefits of customization including:
  • Making fields, with your own validations (Regex).
  • Making very complex fields ( you can make any control you want, grids , any other controls that achieves your logic).

So if you would want to work as a Sharepoint developer, you will find field customization is one of the most important tasks you wull end up doing on a Sharepoint site.

In this article and attached code, we will make a Looup control, which is available in the standard fields in sharepoint but ours will read its data from another Sharepoint list that is available on the root site, and it will read data depending on the current culture of our page that shows the control. Once selected the data will be saved in its culture, and its very easy when showing this field in any other control to show the field corresponding to the current culture.

Here is our custom control files description:

  1. Control.ascx - a user control with just the sharepoint library referenced in with a rendering template that we will talk about it later on.
  2. ControlField.cs - a class that contains 2 classes that will work as the code behind of the Control.ascx and also contains the class that handles the actions of the field.

First, let's take a look at Control.ascx:





here the most important notes in this control;
  • we clear all the references to the code behind file that exists in the code.
  • then we reference the Microsoft.Sharepoint dll in our control.
  • then create RenderingTemplate in which we will place our controls that we will work on.
Now we are going to see what the .cs file contains;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using Microsoft.SharePoint; // dll that contains SPField classes.

using Microsoft.SharePoint.WebControls; // dll that contains the class of BaseFieldControl.

using System.Web.UI.WebControls;

using System.Threading;

namespace SpCustomFields

{

/*this is the first class we have that represents the SPField and how its rendered

and how its value is shown to users. it should inherit from the same field as you want to represent

for example if you are going to make a text box you should inherit from SPTextField , or if its

a dropdown you should inherit from SPFieldChoice and so on ... */

public class DropDownField : SPFieldChoice

{

/*constructor of the class DropDownField , represents the constructor of

the custom field it self , it will be called when you create a new custom field

in sharepoint , and the parameters passed to this constructor

are ( the control it self , and the title of it ). the both constructors must inherit

from the base which means that you will invoke the base constructor*/

public DropDownField(SPFieldCollection spFieldCollection,string spName)

base(spFieldCollection, spName)

{ }

/* another constructor of the DropDownField class which takes 3 parameters , and they are the control it self

and its title and the display name*/

public DropDownField(SPFieldCollection spFieldCollection,string spName, string spDisplay)

base(spFieldCollection, spName, spDisplay)

{ }

/*this function is called to create an instance from DropDownImplementation class that represents our control code behind

and it returns as the control will be used.*/

public override BaseFieldControl FieldRenderingControl

{

get

{

BaseFieldControl dropDown = newDropDownImplementation();

dropDown.FieldName = this.InternalName;

return dropDown;

}

}

/* function that used to get the field value to save it , in the list physically so any validations could be made here

before you return the value to be saved , as here we make a validation on the dropdown , so if its required the

user must choose one of the items rather than the first item which is empty and here to show a label to the

user when the validation fails we throw an exception called SPFieldValidationException that shows this label

and prevents saving */

public override object GetFieldValue(string value)

{

if (this.Required == true && string.IsNullOrEmpty(value))

{

throw new SPFieldValidationException("You must specify a value before saving");

}

return base.GetFieldValue(value);

}

}

/* this is the second class that represents the code behind of our control , and it inherits from BaseFieldControl */

public class DropDownImplementation : BaseFieldControl

{

//our control

DropDownList ServicesDropDown;

// returns the template name. used to load the user control and detect its rendering template.

//must be the same as the id of our RenderingTemplate used in our .ascx file.

protected override string DefaultTemplateName

{

get

{

return "DropDownRenderingTemplate";

}

}

//function used to focus on our control.

//the function EnsureChildControls() is used to be sure that the controls are rendered and didnt return null.

public override void Focus()

{

EnsureChildControls();

base.Focus();

ServicesDropDown.Focus();

}

//function used to create the controls, here you will need to specify the controls you need to render them in

//each case like when creating new item or editing an existing one.

protected override void CreateChildControls()

{

base.CreateChildControls();

//TemplateContainer represents our loaded .ascx so we can search the ID of our dropdown and use it.

ServicesDropDown = (DropDownList)TemplateContainer.FindControl("ServicesDropDown");

//ControlMode represents our control mode such as adding new item or editing an existing one.

//the modes are stored in enum called SPControlMode.

if (ControlMode == SPControlMode.New || ControlMode==SPControlMode.Edit)

{

//this code gets the list name entered by the user as a description or

//additional data when creating the new column and "ListName" represents the

//the name of the text box that the user will enter the list name in that

//created in the xml file.

string lstName = (string)this.Field.GetCustomProperty("ListName");

ServicesDropDown = FillInDropdown(ServicesDropDown, lstName);

}

}

//our function used to get the items of the dropdown from another list depending on the

//current culture.

private DropDownList FillInDropdown(DropDownListServicesDropDown,string lstName)

{

SPList drpDownLst =SPContext.Current.Site.RootWeb.Lists[lstName];

if (drpDownLst != null)

{

ServicesDropDown.Items.Add(string.Empty);

foreach (SPListItem itm in drpDownLst.Items)

{

if(Thread.CurrentThread.CurrentCulture.ToString().ToLower().Contains("ar"))

{

ServicesDropDown.Items.Add((string)itm["Title"]);

}

else

{

ServicesDropDown.Items.Add((string)itm["TitleEnglish"]);

}

}

}

return ServicesDropDown;

}

//this property is used to show data in the list after addition or when editing it assigns the

//control to the data entered before.

public override object Value

{

get

{

EnsureChildControls();

return ServicesDropDown.SelectedValue;

}

set

{

EnsureChildControls();

ServicesDropDown.SelectedValue=(string)ItemFieldValue ;

}

}

}

}

now we are going to see the last file we have , and this file is very important , because it combines all the files we have to work together .
its the XML file and it contains ;
this file contains ;
  1. you must becarefull of your file name for example if you going to name the control SPCustom.DropDown.ascx your xml file must be name as follow , fldtypes_SPCustom.xml and give the .cs any name you want.
  2. in the previous xml the tag TypeName must be the name of the .ascx which is regarding to point 1 it will be DropDown only without SPCustom at the begining of the .ascx name.
  3. the tag ParentType its the raw type of the control you are using which is here Choice , in case of text box for example it will be Text , or in case of Multiple text it will be Note and so on ...
  4. then the tags TypeDisplayName its a display name of the type of your control and the TypeShortDescription it will be the display name in which the control will appear to you in the sharepoint.
  5. UserCreatableTag must be here = true so the user can create fields from it.
  6. FieldTypeClass will reference to your .ascx main class which is called DropDown.
then there is an important tag which is PropertySchema this tag contains alot of important point like:
  • you can here define fields , that will appear in the additional data part , that appears to you when creating a new column.
  • as you see here i ve defined ListName which i ve invoked in the code by the function GetCustomProperty("ListName") so by that i can read the data entered by the user defining the list name we will our dropdown from.
  • then i can define some properties for this fieldtype like required or not , and display size and so on.
by that you can make a successful custom field , but there is another small part which is missing , which is the deployment of your files

its very easy to deploy your files and they are 3 steps :
  1. put your .ascx @ rootdir:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\CONTROLTEMPLATES

  2. put your xml file @ rootdir:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\XML

  3. put your dll in the GAC @ rootdir:\WINDOWS\assembly
and by now you can enjoy creating and using your custom fields , making all your logic available and easy to perform...