Altering either the design or the behavior of the standard forms that are used to display, edit existing list items or create new ones is a frequent customer request.
In this post I introduce you a technique I apply daily for such tasks, and give a few examples of possible applications. In later posts I plan to provide examples for the most interesting ones.
The standard forms I’m talking about are DispForm.aspx, EditForm.aspx and NewForm.aspx. Of course, you can customize further your existing custom forms as well using the very same technique.
Create an Empty SharePoint Project in Visual Studio 2010.
Create a SharePoint mapped folder that points to the ControlTemplates folder.
Right click on the ControlTemplates folder in Solution Explorer and select Open Folder in Windows Explorer.
Create a new Text Document file and rename it to MyCompany_MyListForm.ascx. Of course, you can use other file names either as long as you keep the file extension and the name is not conflicting with other files in 14\TEMPLATE\CONTROLTEMPLATES.
Drag’n drop MyCompany_MyListForm.ascx from Windows Explorer to the ControlTemplates folder in Solution Explorer of Visual Studio.
Open 14\TEMPLATE\CONTROLTEMPLATES\DefaultTemplates.ascx in a text editor.
Copy the header section of the user control file (all elements beginning with <%@) from DefaultTemplates.ascx and paste it to MyCompany_MyListForm.ascx in Visual Studio.
Add the following line to MyCompany_MyListForm.ascx (replace TagPrefix and namespace attributes with your ones if you wish, but keep them consistent with later changes in names):
<%@ Register TagPrefix="MyControls" Assembly="$SharePoint.Project.AssemblyFullName$" namespace="MyNameSpace"%>
Look up the RenderingTemplate having id="ListForm" in DefaultTemplates.ascx, select and copy this entire RenderingTemplate.
Close DefaultTemplates.ascx and if prompted, do not save any changes.
In MyCompany_MyListForm.ascx, paste the RenderingTemplate you copied earlier, and set its id attribute to MyListForm.
In MyCompany_MyListForm.ascx, look up this control:
<SharePoint:ListFieldIterator runat="server"/>
and replace it with this:
<MyControls:MyListFieldIterator runat="server"/>
Add a new Class to your SharePoint project (let’s call it MyListFieldIterator.cs), set the namespace to MyNameSpace and add:
using Microsoft.SharePoint.WebControls;
Alter the class definition as:
public class MyListFieldIterator : ListFieldIterator
We finished to create the base of the customized ListFieldIterator. Build and deploy the solution.
Using SharePoint Designer, select a site and list you would like to use with the new ListFieldIterator. Open the form you would like to alter. You can change any or all of DispForm.aspx, EditForm.aspx, NewForm.aspx.
Look up the ListFormWebPart in the Code view and add a new property TemplateName with the value set earlier as the id attribute of the RenderingTemplate to the WebPart:
<TemplateName xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">MyListForm</TemplateName>
Of course, if the TemplateName already exists there, you should update its value instead of creating a new one.
Note: Instead of using SPD you can deploy this settings from your SharePoint solution as well. For example, we typically deploy it using a custom feature receiver that utilize the SPLimitedWebPartManager and Reflection to set web part properties. I might be to blog about that later as my time allows.
Save the form in SPD and open the list using the web UI. Select an item to display / edit, or start to create a new item base. You should not see any difference now.
Switch back to VS, and add the text Hello World to MyCompany_MyListForm.ascx, just after the opening <Template> tag. Redeploy the solution and check the altered forms on the web UI. The Hello World message should be now visible.
At this point you may say it is much ado about nothing. I admit it is not the simplest way to display a message, but all we discussed earlier is only the base of a framework we can use later to achieve some really powerful results. Just to name some of them:
- You can add custom activity to your form that is performed when the item is saved or specify what action to perform instead of saving. For example, you can cancel saving, send a mail, create a task, set permissions or even call external components.
- You can interact with the list field controls and other controls on the form as well. You can hide some of the controls or set them to read-only mode even in the edit / new mode.
- You can create custom field control arrangements in place of the standard one column multiple rows (one per field) form design.
- Through your control you can insert a link to a custom JavaScript / jQuery file that adds dynamic behavior to your form.
- You can interact with the ribbon from your custom ListFieldIterator, for example, you can disable ribbon elements based on your business requirements.
- You can do custom validation. Although SharePoint 2010 provides validation at the form and the field level, both of these have their limitations. Sometimes you simply need to have multiple validation rules and error messages for a single form / field and you might need to validate field types not supported by the out of the box validation (lookup or user fields, managed metadata or even your custom field types).
If you read my post about custom field types vs. event receivers in the past, you can recognize some of the possibilities listed there, like this one about validation or this other one about hiding fields or displaying them as read-only in edit / new mode. It’s not a random coincidence, you can use both of these methods to achieve the same goals (after all, you can get a reference to the ListFieldIterator instance from the custom field and vice versa), however I recently prefer the technique of custom ListFieldIterator, simply because I found it is simpler and more powerful, easy to maintain and deploy, and probably fits better to the whole picture of form customization.