Introduction
This article talks about a simplified way of creating controls for fields of SharePoint List in WebPart. This uses SP FormField control to create controls for SP list instead of basic ASP.NET controls. With FormField control, a developer can manage the appearance of controls as per his/her requirement very easily. The reader is expected to have sufficient knowledge of creating, deploying WebPart for SharePoint 2007. If you are new to WebPart or SharePoint, please see other articles to understand WebPart and SharePoint 2007 before reading this article.
Background
SharePoint by default provides "Add New" and "Edit" pages for SP Custom List. But it will display all controls in edit mode. Many times, you need to display page with only few column controls or editable controls depending upon business logic. To achieve this dynamic control creation, one can use WebPart and completely control display of columns. The controls for a field/column of List can be created in ASP.NET. But this means one has to write a code to:
- identify type of control
- populate control with master data like that in dropdown list
- set proper value from List Item to control
SharePoint provides a wrapper to various controls but even then, you need to pick a suitable control for a given field. All this means that the developer needs to write and maintain code for each field separately.
SharePoint also provides FormField control that can really help a developer to get rid of common work of selection of control, populating the control with data and allows the developer to concentrate on business logic he/she wants to put in WebPart.
Using the Code
First, add the following Microsoft.SharePoint.dll reference to your WebPart project. Include the following namespaces in your WebPart
class. The language used in this article is C#.
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Utilities;
FormField internally uses properties of SP Field to decide which control is to be created, what data should be populated. Below are the important properties of FormField that help a developer to tie up control to specified Field and Item of the List:
ListId | This is the GUID of List. |
FieldName | This is the internal name of Field. Using ListId and FieldName control gets necessary Field details. |
ControlMode | Display - Control is created for read only data. New - Editable control is created with default value. Populates master data if required. Edit - Editable control is created with value from Item of the List. Required ItemId property set. |
ItemId | This is an item id of the record in List. For Edit mode, this has to be provided so that item data value can be set to control. |
ID | Unique Id of the control that developer must set. This helps the developer to find control on page while retrieving data filled by user in control. |
Value | The property helps the developer to set default value or get user entered value from the control. |
To create SP Controls in WebPart, first you need to get List, Fields and Item objects of SP Custom List.
string mylistName = "FormField_Demo_List";
int itemIndex = 0;
SPWeb myweb = SPContext.Current.Web;
SPList mylist = myweb.Lists[mylistName];
SPItem = mylist.GetItemById(itemIndex);
SPField field1 = mylist.Fields.GetField("Field1");
SPField field2 = mylist.Fields.GetField("Field2");
SPField field3 = mylist.Fields.GetField("Field3");
To dynamically create controls, one can take leverage of SP View to maintain list of fields to be displayed in WebPart, e.g. you can create "DraftView
" on list and add only editable fields to this SP View and this view can be internally used in WebPart to determine which fields should be shown in editable mode for a record in Draft status.
for (int i = 0, size = formView.ViewFields.Count; i < size;)
{
field = list.Fields.GetFieldByInternalName(formView.ViewFields[i]);
....
....
}
The next step is to create instances of FormField
control for each Field of the List
and add it to WebPart's Control
collection. For each FormField
control, you have to set ControlMode
and other properties. The following method helps to achieve the same.
public FormField GetFormFieldControl
(Guid listId, SPItem item, SPField field, SPControlMode mode, object defaultValue)
{
FormField formField = new FormField();
formField.ListId = listId;
formField.FieldName = field.InternalName;
formField.ID = string.Format("Field_{0}",
field.InternalName);
formField.ControlMode = mode;
SPControlMode.New || SPControlMode.Edit
if (item != null)
{
formField.ItemId = item.ID;
}
if (field.Type == SPFieldType.Note || field.Type == SPFieldType.Text)
{
formField.CssClass = "ms-short";
}
if (defaultValue != null)
{
formField.Value = defaultValue;
}
return formField;
}
The FormField control will render the necessary control on page and the user can see the controls just like default New and Edit page controls. To retrieve data/value entered by user in the control, you can use the following methods:
public object GetSharePointControlValue(ControlCollection Controls, SPField field)
{
string fieldName = string.Format("Field_{0}", field.InternalName);
Control returnObject = null;
if (Controls != null)
{
foreach (Control control in Controls)
{
returnObject = FindControlRecursive(control, fieldName);
if (returnObject != null)
break;
}
}
if (returnObject != null && returnObject is FormField)
{
return ((FormField)returnObject).Value;
}
return null;
}
public Control FindControlRecursive(Control Root, string Id)
{
if (Root.ID == Id)
return Root;
Control FoundCtl = null;
foreach (Control Ctl in Root.Controls)
{
FoundCtl = FindControlRecursive(Ctl, Id);
if (FoundCtl != null)
return FoundCtl;
}
return null;
}
The following code updates the value in List Item:
item[field.InternalName] = this.GetSharePointControlValue(this.Page.Controls, field);
item.Update();
Sometimes it's a good idea to use customised display of data in table cell instead of using FormField to display content in read only mode. This can be achieved using GetFieldValueAsHtml()
method of SPField
that returns HTML tags for the data of the given field of item.
TableCell cell = new TableCell();
cell.VerticalAlign = VerticalAlign.Top;
cell.CssClass = "ms-formbody";
if (item[field.InternalName] != null)
{
string data = field.GetFieldValueAsHtml(item[field.InternalName]);
if (false == string.IsNullOrEmpty(data))
{
cell.Text = data;
}
else
{
cell.Text = "[Unable to render data]";
}
}
else
{
cell.Text = " ";
}
Points of Interest
FormField provides a powerful way of representing SharePoint controls on page. You can easily configure it to take leverage of SharePoint styles and formats. You can now concentrate on business logic and forget about control creation activities. It's always interesting to see text in Value property for complex fields like People/Group, Lookup, Radio, etc.
History
Version | Description |
1.0 | Initial version |
1.1 | New instance creation for SPWeb removed Item object retrieved using GetItemId method |
The author is Technical Architect and has experience in architecture, design and development of Web applications in ASP.Net along with SQL Server 2005. He has also worked on MOSS 2007.