Sunday, April 26, 2009

Making SharePoint Title a Calculated Column

All SharePoint lists start with a user editable "Title" column that ECB menu's hang off of and that is the default field to display in associated child tables. This works well most of the time. For example if you have a list like Company, you can change the display name of Title to "Company Name," and then Employee records display that field for their parent relationship.

Where this doesn't work well is lists like Employee, where there is no single column that uniquely identifies a row to an end user. You could create a new "Full Name" calculated column and delete the Title column, but making Title a calculated column just feels like a cleaner solution.

I looked into making Title calculated where it is defined in CAML, but it looked pretty messy, and a true calculated column additionally suffers from the limitation that you can’t pull from other lists. The solution I settled on was to populate it in ItemAdding and ItemUpdating. Of course you tie into those methods with something like:

SPList employeeList = site.Lists["Employee List"];
employeeList.EventReceivers.Add(
    SPEventReceiverType.ItemUpdating,
    "[four part assembly name]",
    "Namespace.EmployeeEventReceiver"
   
);
employeeList.EventReceivers.Add(
    SPEventReceiverType.ItemAdding,
    "[four part assembly name]",
    "Namespace.EmployeeEventReceiver"
   
);

The only reason this is worth documenting is because setting title is a little messy in the event receivers and there is very little documentation on how to do it.

public class EmployeeEventReceiver : SPItemEventReceiver {

  public override void ItemAdding(SPItemEventProperties properties) {
    string fullName = GetFullName(properties);
    properties.AfterProperties["Title"] = fullName;
    base.ItemAdding(properties);
  }

  private static string GetFullName(SPItemEventProperties properties) {
    string firstName = properties.AfterProperties["First_Name"].ToString();
    string middleName = properties.AfterProperties["Middle_Name"].ToString();
    string lastName = properties.AfterProperties["Last_Name"].ToString();
    return Employee.GetFullName(firstName, middleName, lastName);
  }

  public override void ItemUpdating(SPItemEventProperties properties) {
    string fullName = GetFullName(properties);
    string internalTitleName = properties.ListItem
        .Fields["Title"].InternalName;
    properties.AfterProperties[internalTitleName] = fullName;
    base.ItemUpdating(properties);
  }
}

The tricky part is getting the title field by internal name in ItemUpdating vs. getting it normally in ItemAdding. It’s pretty easy once you work through it, but it took me longer than it should have. So hopefully this helps someone somewhere.

1 comment:

Sandeep K Nahta said...

i will say ..renaming was much cleaner solution.. event receivers are buggy..

u might like to change the display pattern of title field..

something like this
http://snahta.blogspot.com/search/label/Title