Microsoft

Blog Categories

Subscribe to RSS feed

Archives

Using Custom Field Types and List Item Event Receivers to Display Multiple Columns of Data

Overview

Custom Field Types are a powerful SharePoint feature that allow you create your own field types for use in list definitions. When creating a Custom Field Type, you can customize not only the data types that are stored in the list field, but also the user interface and validation logic for the field as well.

One very useful kind of Custom Field Type is a multi-column field. This kind of field allows you to store multiple related values in single field. These values are stored together in a delimited string and are available in code using an array-like syntax. To create a multi-column field, your Custom Field Type should inherit from SPFieldMultiColumn. This type hides the details behind storing and retrieving the field column values in the delimited string and provides the array-like API for accessing these values.

One case in which a multi-column Custom Field Type is useful is when you want to have a complex UI with multiple elements that must interact with each other in some way. For example, take a case from a current project in which we are building an online platform for hosting medical journals. One feature of this platform allows the journal editor to choose articles from various issues of the journal to highlight on the journal home page as “Editor’s Picks”. When picking an article to highlight, the editor also has the option to choose one of the images from the article to display along-side the article title in the “Editor’s Picks” list.

Approach

To implement this feature, we created a SharePoint list to hold the selected articles and built a Custom Field Type that allows the users to pick an article from a tree view that displays all of the articles published in the journal organized by year and issue. The Custom Field Type also includes a popup panel that allows the user to browse the images associated with the selected article and to choose an image for display. Both the ID of the article and the URL of the image are stored as columns in the multi-column field.

One drawback of field types that derive from SPFieldMultiColumn is that they are not sortable, groupable, or filterable in list views. This prevents you from using many built-in features of the List View Web Part at either design time or run time. In our example we wanted to display the article title in one column of our list view and the article author in the next column. Additionally, both of these columns had to be sortable. To accomplish this, we stored both of these values in the multi-column field along-side the article ID and image URL. This was necessary because these have to be retrieved when the article is picked in list edit mode so that they are available to be displayed in list view mode.

Once we had the information we wanted to display, we needed some way to overcome the sorting/filtering limitations of the multi-column field. This is where the List Item Event Receivers came into play. In the list definition, we created additional text fields for Article Title and Article Author. Because these fields use the built-in Single Line of Text data type, they are fully sortable/filterable in list views. To populate these fields with the desired values, we implemented List Item Event Receivers and hooked them up to the ItemAdded and ItemUpdated events. Both of these receivers copy the title and author values out of the multi-column field and store them in their respective text fields. We now had our desired values available in columns that were sortable in list views.

The last step in implementing this solution was to ensure that the text fields are hidden from the user when adding or editing a list item. We accomplished this by setting a few attributes on the field definition in the list schema file. The Field element in the list schema defines attributes called ShowInNewForm, ShowInEditForm, and ShowInDisplayForm that can be set to false in order to hide a field in a given form.

Creating the Custom Field Type

Creating your own Custom Field Type requires four things:

1) A user control (i.e., .ascx file) that defines the UI for the field

2) A class that derives from Microsoft.SharePoint.SPField (or one of its subtypes) to define the field itself

3) A class that derives from Microsoft.SharePoint.WebControls.BaseFieldControl (or one of its subtypes) that acts as the code-behind for the user control

4) An XML file that is names fldtypes_xxxx.xml where “xxxx” is any custom name you want to use.

Once the .ascx file and XML files are deployed under the TEMPLATE folder in the 12 hive, the Custom Field Type will be available for use in lists in your SharePoint sites.

For further information on implementing and deploying a Custom Field Type, I refer you to the excellent documentation on MSDN (http://msdn.microsoft.com/en-us/library/ms446361.aspx) or one of the many blog posts on the topic.

Creating the Event Receivers

Creating and deploying an Event Receiver requires three things:

1) A class that derives from Microsoft.SharePoint.SPItemEventReceiver and overrides the appropriate methods to handle the desired event (e.g., ItemAdded, ItemUpdated, ItemDeleted)

2) A feature that defines the list template

3) A class derives from Microsoft.SharePoint.SPFeatureReceiver and overrides the FeatureActivated method to create the list and register the Event Receivers.

Below are code examples for the Event Receiver and Feature Receiver classes:

public class CustomEventReceiver : SPItemEventReceiver

{

public override void ItemAdded(SPItemEventProperties properties)

{

try

{

base.ItemAdded(properties);

updateItem(properties);

}

catch (Exception ex)

{

//Do something to handle the exception

}

}

public override void ItemUpdated(SPItemEventProperties properties)

{

try

{

base.ItemUpdated(properties);

updateItem(properties);

}

catch (Exception ex)

{

//Do something to handle the exception

}

}

private void updateItem(SPItemEventProperties properties)

{

SPFieldMultiColumnValue value =

properties.ListItem[ARTICLE_INFOREMATION] as SPFieldMultiColumnValue;

properties.ListItem[ARTICLE_AUTHORS] = value[3];

properties.ListItem[ARTICLE_TITLE] = value[2];

properties.ListItem.Update();

}

}

public class MyFeatureReceiver : SPFeatureReceiver

{

public override void FeatureActivated(SPFeatureReceiverProperties properties)

{

try

{

// feature is scoped at Site, so the parent’s type is SPSite rather than SPWeb..

SPSite site = properties.Feature.Parent as SPSite;

SPWeb web = site.RootWeb;

//Create the list

createMyCustomList(web);

string assemblyName = System.Reflection.Assembly.GetExecutingAssembly().FullName;

web.Lists[Settings.ListNameArticleCollections].EventReceivers.Add(

SPEventReceiverType.ItemAdded, assemblyName, "CustomEventReceiver”);

web.Lists[Settings.ListNameArticleCollections].EventReceivers.Add(

SPEventReceiverType.ItemUpdated, assemblyName, "CustomEventReceiver”);

}

catch (Exception exception)

{

//Do something to handle the exception

}

}

}

The event receiver class overrides ItemAdded and ItemUpdated to copy the values from the multi-column field (ARTICLE_INFORMATION) to the text fields (ARTICLE_AUTHOR and ARTICLE_TITLE).

The feature receiver class overrides FeatureActivated to create the list and hook up the event receivers. This class can also override FeatureDeactivating to delete the list when the feature is deactivated.

Below is a snippet from the feature manifest (feature.xml) that shows how to register the feature receiver:

<Feature Id="17CF06F2-7748-4762-9E6D-3AD7830C05D0"

Title="My Custom List Feature"

Description="Creates a list based on the list definition and wires up the related event

receivers"

Version="1.0.0.0"

Scope="Site"

ReceiverAssembly="MyFeatureReceiverAssembly, Version=1.0.0.0, Culture=neutral,

PublicKeyToken=123456789abcdefgh"

ReceiverClass="MyFeatureReceiver"

xmlns="http://schemas.microsoft.com/sharepoint/">

Hiding the Text Fields in the New and Edit Forms

To ensure that the users cannot edit the title and author text fields, these field must be hidden on the new and edit forms of the list. Hiding these fields is easily accomplished by setting their ShowInEditForm and ShowInNewForm attributes to false in the list schema definition.

Below is a snippet from the Schema.xml file for the list:

<Fields>

<Field ID="{F4D43BF4-6EC1-48aa-99D9-B8BE45DE5EFF}"

Name="ArticleTitle"

Group="Journals Site Columns"

DisplayName="Article Title"

Type="Text"

Required="FALSE"

Sealed="TRUE"

StaticName ="ArticleTitle"

ShowInEditForm ="FALSE"

ShowInNewForm ="FALSE">

</Field>

<Field ID="{7D5F6429-13E7-47e6-B53F-89889B269889}"

Name="ArticleInformation"

Group="Journals Site Columns"

DisplayName="Article Information"

Type="ArticlePickerField"

Required="TRUE"

Sealed="TRUE"

StaticName ="ArticleInformation">

</Field>

<Field ID="{2F119CFD-6CDF-4362-B548-35039F8434CA}"

Name="ArticleAuthor"

DisplayName="Article Author"

Description="Single line of text"

Group="Journals Site Columns"

Type="Text"

Sealed="TRUE"

Required="FALSE"

ShowInEditForm ="FALSE"

ShowInNewForm ="FALSE">

</Field>

</ Fields>

The field named ArticleInformation is our multi-column Custom Field Type. ArticleTitle and ArticleAuthor are the Single Line of Text fields that hold the title and author values for display purposes. Notice that both of these fields have their ShowInEditForm and ShowInNewForm attributes set to “FALSE”.

Leave a Reply