SPListItem properties metadata columns with c#
Thursday, May 22, 2008, 12:51 -
SharePointPosted by Administrator
There are some funny things going on inside SharePoint, and this is one of the funniest…
We have a list, with two fields:
<Field
Type="Text"
DisplayName="Category"
MaxLength="255"
Name="Category0"
ColName="nvarchar17"
/>
<Field
Name="Category"
FromBaseType="TRUE"
Type="Choice"
DisplayName="Category (deprecated)"
Format="Dropdown"
FillInChoice="FALSE"
ColName="nvarchar2"
><!-- CHOICES --></Field>
Note that one has the DisplayName of ‘Category’ and the other has the Name of ‘Category’.
The one with the Name ‘Category’ is deprecated, and we actually want to populate the field with the DisplayName ‘Category’.
You’d expect this would be fine… so consider that we have an empty list and that we create a new item and try and populate the item:
SPListItem newListItem = spList.Items.Add();
newListItem["Title"] = "The title";
newListItem["Category"] = "Category 1";
newListItem.Update();
That should work right? I mean MSDN very plainly states that on a SPListItem that you access a field using the DisplayName of the SPField that you want to set the value against.
It tries to populate the wrong field.
Why? Because it seems that if a SPField exists that has an InternalName the same as a DisplayName, then that SPField takes priority. As the Name property of a SPField *is* the InternalName, we’ve actually just attempted to assign the string “Category 1″ to the Choice Field that is “Category (deprecated)”.
A very subtle but pain in the arse thing that.
So how to get around it? Well, instead of passing in the DisplayName you can use the overloaded version of spListItem[] to pass in the int32 index of the SPField in the spList.Fields collection.
So if you loop the spList.Fields collection, work out where the real “Category” field is that we want to update, and grab the index… you’d expect to be able to update the list item right?
Right, but… not if the item you are creating is the first item to ever go into the list. It will work for every subsequent item, but never the first item.
For some reason the index based accessors only work after an item exists, so if we go back to that original piece of code and update it with the Field index:
SPListItem newListItem = spList.Items.Add();
newListItem["Title"] = "The title";
newListItem[2] = "Category 1";
newListItem.Update();
That won’t work.
Instead you have to save the item, and then grab a fresh instance of the item and save that:
SPListItem newListItem = spList.Items.Add();
newListItem["Title"] = "The title";
newListItem.Update();
SPListItem existingListItem = spList.GetItemByID(newListItem.ID);
existingListItem[2] = "Category 1";
existingListItem.Update();
And that piece of code works.
The rules here:
- You can’t set a value to a field using the DisplayName if another field exists with a matching Name / InternalName.
- You can’t use the index based accessors until an item exists within the SharePoint list.