Monday, October 24, 2011

A pattern for building custom forms in SharePoint 2010

Recently, I have been working on a pretty large enterprise intranet
project on SharePoint 2010 that involves building a few modules that meet the
business needs. These modules each involve a few related content types. The way
we architected these was to have a main core content type for each module – and
have a few other content types have a lookup column back to that core content
type. There were some one-one relationships as well as one-many relationships
in the mix. Given that there were these related entities, there is no OOB way
to allow for a seamless experience for an end user to go through the entire
process of creating the core entity and all related entities without needing to
know how they are stored in custom lists. There were also event receivers that
needed to be created in these modules that would do sub-tasks, set permissions
on items, send email etc.

One of our key design goals from the onset was to make the
user experience as friendly as possible while at the same time accounting for
any changes/additions to fields to the content types after the project was
delivered. So we did not want to build fully custom forms, because those would
be tied strongly to the schema as we knew it during development and would need
a UI change and deployment to add any new field to the custom pages

.

Here is an example of content types in one specific
(relatively simple) module:

The approach we took was making extensive use of list field
iterators in SP 2010. These are available in the SP API and are fairly easy to
use once you get the hang of these. So these would allow us to point the
ListFieldIterator to a list in SharePoint and set its mode to New, Edit or
Display. What this would do is open up the list item in one of those modes. The
iterator iterates through all the fields in that list and surfaces them to you,
just like in an OOB SharePoint list form. If we needed to edit or display we
would also bind the list item ID to the iterator and set the corresponding
mode. If the user did not have permissions to edit the list item, we would show
the iterator in the display mode.

Here is how the new/edit form looked with the iterators.

We used the Tab control in the AjaxControlToolkit to manage the
UI using different iterators in the tabs. We also employed the modal framework
quite extensively to manage sub types as shown below. Here is the management screen for audit tracking.

On clicking new audit tracking entry, the user would get this screen as show below. Notice the Tab control and how the result looks like an OOB list form. It is easy to bind the iterator to the list and the item and set its mode (New, Edit or Display). The buttons below are custom and thus the saving has to be done by you as well.

You can click the new Audit Finding link to create a new sub type. Here is that screen.

As you can see above, this really is a SharePoint modal dialog showing yet two more sub content types in their own lists and related to the main core Audit content type. The modal framework is really handy for doing these sort of things and improving the user experience vastly. Imagine if the user had to go to 5-6 different lists to create a new audit, to say that would not fly would be an understatement!

Here is some code that highlights how to bind these. Here is the code to declare the iterator.

In the code behind, this is how you bind it.

SPList AuditTrackingList = SPContext.Current.Web.Lists[Constants.AUDIT_CORE_LIST_NAME];
ListFieldIteratorAuditTracking.ListId = AuditTrackingList.ID;
//Set the mode as well depending on whether you are opening an existing one to display or new one. lets go with new for here
ListFieldIteratorAuditTracking.ControlMode = SPControlMode.New;
//Could also be SPControlMode.Edit or SPControlMode.Display

Voila, your iterator binds to the list item and shows it just like SharePoint would.

To update/save, in your Button_Save event (obviously this is oversimplified):