Share via


Creating Multicolumn SharePoint 2010 Field Types

SharePoint Visual How To

Summary:  Learn how to work with multicolumn values when creating custom field types in Microsoft SharePoint 2010 to track two or more pieces of data that represent one logical piece of information.

Applies to: SharePoint Foundation 2010 | SharePoint Server 2010 | Visual Studio | Visual Studio 2008 | Visual Studio 2010

Provided by:  Ted Pattison, Critical Path Training, LLC (SharePoint MVP)

Overview

Let's say that you have to write a business solution in which you track two or more pieces of data that make up one logical piece of information. One example of this might be a United States address that contains a street address, city, state, and ZIP Code. This Microsoft SharePoint Visual How To demonstrates how to create a multicolumn custom field type to track a United States address. This address contains five different pieces of data, but it also represents one logical piece of content in a Microsoft SharePoint 2010 list.

Code It

The sample custom field type named UnitedStatesAddress that is demonstrated in the accompanying video provides an example of how to create a multicolumn field type that tracks an address in the United States. The custom field type provides a column value for five different pieces of data.

Column values that are required to track a United States address:

  • Street Address Line 1

  • Street Address Line 2

  • City

  • State

  • ZIP Code

Creating the Rendering Template

Start by creating an .ascx file that defines the rendering template. You must deploy this .ascx file inside the 14\TEMPLATE\CONTROLTEMPLATE directory. Inside this .ascx file, define the rendering template by using the RenderingTemplate control tag, and give it a unique ID. In this example, you define the editing surface by using an HTML table layout with the following five TextBox controls for user input:

  • txtAddress1

  • txtAddress2

  • txtCity

  • txtState

  • txtZipcode

<SharePoint:RenderingTemplate runat="server"
                        ID="UnitedStatesAddressRenderingTemplate" >
  <Template>
    <table>
      <tr>
        <td>Address1:</td>
        <td><asp:TextBox ID="txtAddress1"  runat="server" /></td>
      </tr>
      <tr>
        <td>Address2:</td>
        <td><asp:TextBox ID="txtAddress2" runat="server" /></td>
      </tr>
      <tr>
        <td class="AddressLabel">City:</td>
        <td>
          <asp:TextBox ID="txtCity" runat="server" />
          &nbsp;State:&nbsp;
          <asp:TextBox ID="txtState" runat="server" MaxLength="2" />
          &nbsp;Zipcode:&nbsp;
          <asp:TextBox ID="txtZipcode" runat="server" />
        </td></tr>
    </table>
  </Template>
</SharePoint:RenderingTemplate>

Creating the Field Control Class

You use the field control class to initialize and manage the controls that are defined within the rendering template. The field control class in the following example initializes the field to reference the controls in the rendering template. It also provides an overridden implementation of the Value property, which is required to write values to and from the content database. The most important aspect of this code that relates to multicolumn field types is that values that have multiple columns are written to and read from the content database using an instance of the PFieldMultiColumnValue class.

public class UnitedStatesAddressFieldControl : BaseFieldControl {
  protected override string DefaultTemplateName {
    get { return "UnitedStatesAddressRenderingTemplate"; }
  }
  protected TextBox txtAddress1;
  protected TextBox txtAddress2;
  protected TextBox txtCity;
  protected TextBox txtState;
  protected TextBox txtZipcode;
  protected override void CreateChildControls() {
    base.CreateChildControls();
    txtAddress1 =
        (TextBox)this.TemplateContainer.FindControl("txtAddress1");
    txtAddress2 =
        (TextBox)this.TemplateContainer.FindControl("txtAddress2");
    txtCity = 
        (TextBox)this.TemplateContainer.FindControl("txtCity");
    txtState = 
        (TextBox)this.TemplateContainer.FindControl("txtState");
    txtZipcode = 
        (TextBox)this.TemplateContainer.FindControl("txtZipcode");
  }

  public override object Value {
    get {
      this.EnsureChildControls();
      SPFieldMultiColumnValue mcv = new SPFieldMultiColumnValue(5);
      mcv[0] = txtAddress1.Text;
      mcv[1] = txtAddress2.Text;
      mcv[2] = txtCity.Text.ToUpper();
      mcv[3] = txtState.Text;
      mcv[4] = txtZipcode.Text;
      return mcv;
    }
    set {
      this.EnsureChildControls();
      SPFieldMultiColumnValue mcv = 
                (SPFieldMultiColumnValue)this.ItemFieldValue;
      txtAddress1.Text = mcv[0];
      txtAddress2.Text = mcv[1];
      txtCity.Text = mcv[2];
      txtState.Text = mcv[3]; ;
      txtZipcode.Text = mcv[4];
    }
  }
}

Creating the Custom Field Class

The class that defines the multicolumn field type must inherit from the SPFieldMultiColumn class. It must also provide two nondefault constructors and an overridden implementation of the FieldRenderingControl property to create and initialize an instance of the field control class. The class in this example also overrides the GetFieldValueAsHtml method to introduce line breaks when it is shown in an HTML view, such as AllItems.aspx.

public class UnitedStatesAddress : SPFieldMultiColumn {
  public UnitedStatesAddress(SPFieldCollection fields, 
                             string fieldName)
    : base(fields, fieldName) { }

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

  public override BaseFieldControl FieldRenderingControl {
    get {
      BaseFieldControl ctr = new UnitedStatesAddressFieldControl();
      ctr.FieldName = this.InternalName;
      return ctr;
    }
  }

  public override string GetFieldValueAsHtml(object value) {
    string HtmlLineBreak = @"<br />";
    SPFieldMultiColumnValue mcv = 
      new SPFieldMultiColumnValue(value.ToString());
    string HtmlAddress  = mcv[0].ToString() + HtmlLineBreak;
    if(!string.IsNullOrEmpty(mcv[1])) {
      HtmlAddress += mcv[1].ToString() + HtmlLineBreak;
    }
    HtmlAddress += mcv[2].ToString() + ", " + mcv[3] + "  " + mcv[4];
    return HtmlAddress;
  }
}
Read It

By creating custom field types, you can create a user interface experience component to provide a custom editing experience. You can also provide custom code that contains logic to validate multiple data values as a whole.

See It

Watch the video

> [!VIDEO https://www.microsoft.com/en-us/videoplayer/embed/b7ec13c9-b08e-4e21-85af-a4f74d08a88c]

Length: 00:12:31

Explore It

About the Author

MVP Contributor Ted Pattison is an author, instructor, and co-founder of Critical Path Training, a company dedicated to education on SharePoint technologies. As a Microsoft SharePoint Most Valuable Professional (MVP), Ted frequently works with the Microsoft Developer Platform Evangelism group to research and author SharePoint training material for developers early in the product life cycle while in its alpha and beta stages. Ted is also co-author of Inside Microsoft SharePoint 2010.