Writing code to get or set data in a lookup field (SPFieldLookup) or its descendant the User field (SPFieldUser) can be a real pain in the eyes. Thankfully there’s a handy couple of classes that can make life easier.
If you’ve ever frowned at “;#” delimiters, and begrudgingly twisted a for
clause to check every other line, then you should most definitely read on.
A bit of background
Most complex field types have a Value
class; a class that handles serialising and deserialising an item’s data for that field. If the field can have multiple values then there is often also a Collection
class (a generic collection in the form List<Value>
).
For lookups these classes are called SPFieldLookupValue and SPFieldLookupValueCollection. For User selections these are SPFieldUserValue and SPFieldUserValueCollection.
Getting single items
If you only have one value in a lookup, then this can be accessed using the following:
SPListItem item = SPContext.Current.List.GetItemById(1);
if (item["LookupField"] != null)
{
string fieldValue = item["LookupField"].ToString();
SPFieldLookupValue value = new SPFieldLookupValue(fieldValue);
int lookupListItemID = value.LookupId;
string lookupListValue = value.LookupValue;
}
Not a single split string in sight. To do the same for a single user field, you do the following:
SPListItem item = SPContext.Current.List.GetItemById(1);
if (item["UserField"] != null)
{
string fieldValue = item["UserField"].ToString();
SPFieldUserValue value = new SPFieldUserValue(SPContext.Current.Web, fieldValue);
SPUser user = value.User;
}
The SPWeb passed into the constructor above is used to resolve the User; if you’re writing cross-site code make sure you pass a Web that recognises the User.
Setting single items
Setting lookups is quite straight forward:
SPListItem item = SPContext.Current.List.GetItemById(1);
int id = 1;
item["LookupField"] = new SPFieldLookupValue(id, string.Empty);
item.Update();
id
is the item ID in the lookup list, and the string.Empty
is the optional (as far as I can tell) display value. The display value is populated using the ID once the item is updated, so we needn’t bother getting it ourselves.
Setting a single user field couldn’t be easier, and requires no special tools, classes, or qualifications:
item["UserField"] = SPContext.Current.Web.CurrentUser;
Multiple items
Now we’re getting into more interesting territory. Multiple choice Lookups can be accessed using the previously-mentioned SPFieldLookupValueCollection. This is a collection of SPFieldLookupValue objects that each represent one of the values.
The collection can be used to get information like this:
SPListItem item = SPContext.Current.List.GetItemById(1);
if (item["LookupField"] != null)
{
string fieldValue = item["LookupField"].ToString();
SPFieldLookupValueCollection values = new SPFieldLookupValueCollection(fieldValue);
foreach (SPFieldLookupValue value in values)
{
int lookupListItemID = value.LookupId;
string lookupListValue = value.LookupValue;
}
}
And to set the item data like this:
SPListItem item = SPContext.Current.List.GetItemById(1);
SPFieldLookupValueCollection values = new SPFieldLookupValueCollection();
values.Add(new SPFieldLookupValue(1,string.Empty));
values.Add(new SPFieldLookupValue(3,string.Empty));
item["LookupField"] = values;
item.Update();
The SPFieldUserValueCollection is used in almost exactly the same way. The only differences are that the constructors require an SPWeb, and SPUser.ID is used for the LookupID.
Pretty neat
Well, I thought so.
All this was probably old news to some, but it was a Christmas stocking of happy surprises for me when I found it. 🙂