Thursday 30 May 2013

Creating Multicolumn SharePoint 2010 Field Types

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.

No comments:

Post a Comment