Dec 7, 2008

Site column and field type

They are different concept. Site column is higher level concept, and field type are lower level. Site column reference field type. Site column examples are City, Company, FirstName. It can be reused when create new content type and list. Field type examples are Text, Choice, Notes. But WSS3 allow user to create a customized field types. The motivation for doing this is to gain a greater level of control over initialization, rendering, and data validation that goes on behind a column.

A example of site column is as follow.


  
    High Tech
    Legal
    Medical
  
  High Tech

A custom field type represents a new data type for columns. A custom field type is wrttern in managed code and compiled into .net assembly that must be installed in GAC. A custom field has two responsibility the business logic, and render UI. So here the UI can be separated into another class, BaseFieldControl.

// example of creating a custom field type
public class CompanySizeField : SPFieldText
{

    public CompanySizeField(SPFieldCollection fields, string fieldName)
        : base(fields, fieldName) { }

    public CompanySizeField(SPFieldCollection fields, string typeName, string displayName)
        : base(fields, typeName, displayName) { }

    public override Microsoft.SharePoint.WebControls.BaseFieldControl FieldRenderingControl
    {
        get
        {
            BaseFieldControl control = new CompanySizeFieldControl();
            control.FieldName = this.InternalName;
            return control;
        }
    }

    // Validate the string. If not valid, throw an SPFieldValidationException
    public override string GetValidatedString(object value)
    {
        if (this.Required || value.ToString().Equals(string.Empty))
        {
            throw new SPFieldValidationException("Company size not assigned");
        }
        return base.GetValidatedString(value);
    }
}

// custom field type uses helper class to initialize and render control
//this FieldControl use a user control to to render
//the TemplateContainer
public class CompanySizeFieldControl : BaseFieldControl
{
    protected DropDownList CompanySizeSelector;

    protected override string DefaultTemplateName
    {
        get
        {
            return @"CompanySizeFieldControl";
        }
    }

    public override object Value
    {
        get
        {
            this.EnsureChildControls();
            return this.CompanySizeSelector.SelectedValue;
        }
        set
        {
            EnsureChildControls();
            this.CompanySizeSelector.SelectedValue = (string)this.ItemFieldValue;
        }
    }

    protected override void CreateChildControls()
    {
        if (this.Field == null || this.ControlMode == SPControlMode.Display)
            return;
        base.CreateChildControls();

        this.CompanySizeSelector = (DropDownList)TemplateContainer.FindControl("CompanySizeSelector");

        if (this.CompanySizeSelector == null)
            throw new ConfigurationErrorsException("Corrupted CompanySizeFieldControl.ascx file.");

        if (!this.Page.IsPostBack)
        {
            this.CompanySizeSelector.Items.AddRange(new ListItem[]{ 
                  new ListItem(string.Empty, null), 
                  new ListItem("Mom and Pop Shop (1-20)", "1-20"), 
                  new ListItem("Small Business (21-100)", "21-100"), 
                  new ListItem("Medium-sized Business (101-1000)", "101-1000"), 
                  new ListItem("Big Business (1001-20,000)", "1001-20000"),
                  new ListItem("Enterprise Business (over 20,000)", "20000+")
            });
        }
    }
}

The field control use a user control as template, so the user control name must be named after the value of DefaultTemplateName property, in this case the name is "ComapanySizeFieldControl" , it should be copied to controltemplates folder.