PANVEGA’s Blog

DotNet Development, SharePoint Customizing, Silverlight, MS Infrastructure and other tips and tricks

Developing Custom Field Types

Posted by PANVEGA on February 18, 2007

In this post i am going to introduce how to develope a custom field type in 6 steps with the Sharepoint People Picker. Search the name you want, push the button in order to resolve the user enitities in the code behind class. Finnaly return the parsed values to a simple multiline text box. You can also create a datagrid or just a table to format the values.

First of all we are going to create the visual user interface. As the custom field will be deployed as an feature assembly, it is a good idea to create a class library project in Visual Studio 2005 or Visual Studio 2008. Prepare also the folder structure that is required for a feature.

Here you have two possibilities:

you can create the necessary controls like labels, text boxes and buttons completely in code. But if your user interface is a bit more complex than just a label and a text box, it is a good idea to design a user control. When working the programmatic way, the user interface is compiled within the custom field assembly.

1.

In this walkthrough the second technique is used. User controls must reside in the CONTROLTEMPLATES directory of SharePoint so add a file with the ascx extension to the corresponding sub folder you just created. In this usercontrol, add a SharePoint:RenderingTemplate control, and insert whatever you want for your control template.

Example:

<%@ Control Language=”C#” %>
<%@ Assembly Name=”PeoplePicker, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxxxx” %>
<%@ Register TagPrefix=”SharePoint” Assembly=”Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” Namespace=”Microsoft.SharePoint.WebControls” %>

<SharePoint:RenderingTemplate Id=”CustomPeoplePicker” runat=”server”>
<Template>
<label title=”information”>Please select an user</label>
<br />
<SharePoint:PeopleEditor runat=”server” ID=”editor” />
<br />
<asp:Button runat=”server” ID=”button” Text=”Resolve Entities” />
<asp:TextBox runat=”server” ID=”editorBox” TextMode=”MultiLine”/>
</Template>
</SharePoint:RenderingTemplate>

Define the ID of the dll assembly in our usercontrol you have to deploy.

Another important PeopleEditor Attribute:

SelectionSet – can be User or SecGroup or SPGroup or all three: User, SecGroup, SPGroup

Tip: You can also add some JavaScript Code to the UserControl file if necessary.

<SharePoint:RenderingTemplate ID=”CustomClass” runat=”server”>

<Template>

<script language=”javascript”>..Code..</script>

<asp:TextBox ID=”txtNumber” runat=”server” MaxLength=”15″ Size=”20″ onkeydown=”javascript:fucntionDOWN(this,event);” onkeyup=”javascript:functionUP(this,event);”/>

</Template>

</SharePoint:RenderingTemplate>

2.

Secondly, create a new control class file (yourClass.cs), which will take the role of codebehind file of the usercontrol. In this class, which will inherit from Microsoft.SharePoint.WebControls.BaseFieldControl, we will override some of the properties and methods to implement our own logic. The BaseFieldControl class renders the field on a form page.

More information about the people picker in an other post: https://panvega.wordpress.com/2008/02/22/custom-sharepoint-people-picker

Example:

namespace PeoplePicker
{
public class PeoplePickerFieldControl : BaseFieldControl
{
protected PeopleEditor editor;
protected TextBox editorBox;
protected Button button;
protected StringBuilder builder = new StringBuilder();

protected override string DefaultTemplateName
{
get { return “CustomPeoplePicker”; }
}

public override object Value
{
get
{
EnsureChildControls();
return builder.ToString();
}
set
{
try
{
//Set the Value into the textbox field
EnsureChildControls();
editorBox.Text = value.ToString();
}
catch(Exception ex) {
throw (ex);
}
}
}

protected override void OnInit(EventArgs e)
{
if(!Page.IsPostBack)
{
base.OnInit(e);
EnsureChildControls();
}
}

public override void Focus()
{
EnsureChildControls();
editor.Focus();
}

protected override void CreateChildControls()
{
Controls.Clear();
base.CreateChildControls();

if (Field == null) return;
//base.CreateChildControls();

//Don’t render the textbox if we are just displaying the field
if (ControlMode == Microsoft.SharePoint.WebControls.SPControlMode.Display) return;

//initializing the values fron the UserControl template to the code behind
editorBox = (TextBox)TemplateContainer.FindControl(“editorBox”);
button = (Button)TemplateContainer.FindControl(“button”);
editor = (PeopleEditor)TemplateContainer.FindControl(“editor”);

if (editor == null) throw new NullReferenceException(“editor is null”);
editor.MultiSelect = true;
editor.ShowCreateButtonInActiveDirectoryAccountCreationMode = true;

if (editorBox == null) throw new NullReferenceException(“editorBox is null”);
if (button == null) throw new NullReferenceException(“button is null”);

button.Click += new EventHandler(button_Click);

if (ControlMode == Microsoft.SharePoint.WebControls.SPControlMode.New)
{

editorBox.Text = “”;
}

}protected void button_Click(object sender, EventArgs e)
{

try
{

ArrayList peEntities = editor.Entities;

for (int i = 0; i < editor.Accounts.Count; i++)
{
// 2. cast object Entities in PickerEntity class
PickerEntity pickEn = (PickerEntity)peEntities[i];

if (pickEn.IsResolved)
{

Hashtable hstEntityData = pickEn.EntityData;
builder.AppendLine(pickEn.DisplayText);
builder.AppendLine(pickEn.Description);

builder.AppendLine(Convert.ToString(hstEntityData[“DisplayName”]));
builder.AppendLine(Convert.ToString(hstEntityData[“Email”]));
builder.AppendLine(Convert.ToString(hstEntityData[“PrincipalType”]))
//…..

editorBox.Text = builder.ToString();
}
}
}
catch (Exception ex)
{
throw (ex);
}}}}

Info:

  • Override the DefaultTemplateName property and pass it the value in the ID attribute of the RenderingTemplate control from the ascx control.
  • The name of the DefaultTemplateName references to your just created custum ascx User Control.

A rendering template. The rendering template is defined in an .ascx file located in C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\ControlTemplates.
This template is used in conjunction with the CreateChildControls method of a rendering control class, to render a field in New, Edit, or Display mode.For more information about rendering templates, see Field Rendering Templates and Patterns of Custom Field Rendering.

other Code snippes:

// Get the current value of the field.
        string currentValue = (string)this.ItemFieldValue;
//other direction
this.Value = this.listBox.SelectedValue;
        this.ItemFieldValue = this.Value;

In order to not rendering the textbox when dispaly you can use:

if (this.ControlMode == SPControlMode.Edit ||
        this.ControlMode == SPControlMode.New){....}

3.

Next thing to do is to create the Field type class (CustomField.cs) itself. In this class, which derives of one of the base control types from SharePoint (SPFieldText, SPFieldChoice, …), we will define which control has to be used as template, and which value has to be returned when displaying a list item. You can add the Item in Visual Studio with the Field Control template when you have installed the extensions in visual studio.

This is very helpful, because the template automatically creates the field type class, control class and the a .snk strong name file in your project. It needs to be signed so we can install it into the GAC.

namespace PeoplePicker
{
public class PeoplePickerField : SPFieldText
{

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

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

public override BaseFieldControl FieldRenderingControl
{
get
{
BaseFieldControl fieldControl = new PeoplePickerFieldControl();
fieldControl.FieldName = this.InternalName;

return fieldControl;
}
}
}
}

As you can see our custom field class inherits from SPFieldText but you can inherit from pretty any other type of SharePoint field. This class essentially controls what happens to the formatting of our fields data as it is retrieved from and inserted into the database.

You can also add the GetValidatedString() function. This function defines what is to be displayed when you display an item.

/// This method validates the data as it is entered into the column. If it doesnt match the criteria a sharepoint exception is thrown.

/// </summary>

/// <param name=”value”></param>

/// <returns></returns>

public override string GetValidatedString(object value)

{

string myVal = value as string;

if (myVal == null)

return String.Empty;

//Strip formating characters from the value..

myVal = myVal.Replace(“(“, “”);

myVal = myVal.Replace(“)”, “”);

myVal = myVal.Replace(“-“, “”);

myVal = myVal.Replace(“+”, “”);

myVal = myVal.Replace(” “, “”);

myVal = myVal.Trim();

//Use regex to makes the string only contains numbers and is within the correct range.

Regex foo = new Regex(“^\\d{10,11}$”);

if (foo.IsMatch(myVal))

{

}

else

{

throw new Microsoft.SharePoint.SPFieldValidationException(“The Telephone number field must contain only numbers, (, ), -, or + characters. It must also be between 10 and 11 digits. val:” + myVal);

}

return myVal;

}

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.

4.

Last file to create is the XML File (fldtypes_custom.xml), which will add the custom field type to SharePoint.

<?xml version=1.0 encoding=utf-8?>

<FieldTypes>

<FieldType>

<Field Name=TypeName>PeoplePicker</Field>

<Field Name=ParentType>Text</Field>

<Field Name=TypeDisplayName>Custom Name Field</Field>

<Field Name=TypeShortDescription>Custom Name Text Field</Field>

<Field Name=UserCreatable>TRUE</Field>

<Field Name=ShowOnListCreate>TRUE</Field>

<Field Name=ShowOnSurveyCreate>TRUE</Field>

<Field Name=ShowOnDocumentLibrary>TRUE</Field>

<Field Name=ShowOnColumnTemplateCreate>TRUE</Field>

<Field Name=Sortable>TRUE</Field>

<Field Name=Filterable>TRUE</Field>

<Field Name=FieldTypeClass>CustomControl.CustomField, CustomControl, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxxxxx</Field>

<Field Name=SQLType>nvarchar</Field>

</FieldType>

</FieldTypes>

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.

5.

So far so good with creating the files Now, all we have to do is put the right files in the right places …
Compile your project (or at least both .cs classes) and make sure they are strong named.
Then, install them in the GAC (%windir%\assembly)

Next, copy the .ascx file to C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\CONTROLTEMPLATES

And the last file to copy: copy the .xml file to C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\XML

6.

Do an IISRESET, and you can use your newly created Custom Field Type

Note:

If you got an error message when creating a new item.

The given key was not present in the dictionary.

Before you initialize your new custom field you have to delete the garbage deletd fields from the field list before.

Important Deployment Information:


Custom field types aren’t deployed using a Feature. The field definition goes in the 12\TEMPLATE\XML directory and the assembly goes in the GAC.

Recycle IIS and you’re good to go. Field types aren’t activated… they are global to an entire farm once deployed.

It does not matter if you change the scope to Site, WebApplication or Web in the feature.xml file. You don´t need the feature.xml file. It is just a Content Deployment.

Refernces:

http://msdn.microsoft.com/en-us/library/bb684919.aspx

http://msdn.microsoft.com/en-us/library/ms446361.aspx


http://msdn.microsoft.com/en-us/library/bb417414.aspx

http://www.ascentium.com/blog/sp/Post80.aspx


http://www.sharethispoint.com/archive/2006/08/07/23.aspx#codetwo

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: