I tend to keep an eye on the sharepoint newsgroups mainly because I can jump in and help someone out with something I've had problems with in the past. One question today on the newsgroup was about adding a hidden field to a sharepoint list via the object model. I've hit this before and until you find out whats going on you feel a bit like you're in a maze of twisty passages all alike.
Often you might want an internal tracking flag or number handled via code that you don't want exposed in the edit list UI that some unsupecting user might then delete by accident.
In theory this should simple.
SPSite spsite=new SPSite(http://localhost:4455); SPWeb web=spsite.OpenWeb(); SPList list =web.Lists["Announcements"]; string id=list.Fields.Add("NewField",SPFieldType.Boolean,false); SPField spfield=(SPField)list.Fields.GetField(id); spfield.Hidden=true; spfield.Update();
But if you try this you'll hit an exception - the reason? The code for the Hidden property checks to see if the property CanToggleHidden property is true and throws an exception if its not.
Fair enough,all we do then is set the CanToggleHidden property to true and do the update but there is no such property on the object model.
There are two ways around this but its best to know some internal details about the SPField object. This way the internal data for a field is stored is in an XML format like this
<Field DisplayName="NewField" Type="Boolean" Required="FALSE" Name="NewField" ColName="bit4" CanToggleHidden="TRUE" Hidden="TRUE"/>
You can see here the CanToggleHiden and the Hidden properties. Note not all fields will have these extra properties if they are not set. The properties are read from /written to via the .dotnet XML classes.
This field definition is a subset of the whole list schema which is taken from the tp_Fields column of the Lists table in the SharePoint content database. The ColName refers to the column used to store the data in the UserData table. You don't need to add this column by hand its automatically calculated from the field type and number of fields of that type already in use.
Now the SPField object internally gets and set its properties into this XML fragment using some helper functions one of which is SetFieldBoolValue for boolean fields, there is also SetFieldIntValue and SetFieldAttributeValue.
The first way to get around the limitation is to add the field directly as XML using the AddFieldAsXml method on the SPFieldCollection using the XML format as above but leaving out the columnname.
list.Fields.AddFieldAsXml("<Field DisplayName=\"NewField\" Type=\"Boolean\" Required=\"FALSE\" Name=\"NewField\" CanToggleHidden=\"TRUE\" Hidden=\"TRUE\"/>");
Thats the supported way but one other interesting method is to toggle the internal CanToggleHidden internal property with reflection.
Add a reference to the System.Reflection namespace and you can do this
Type type = spfield.GetType(); MethodInfo mi= type.GetMethod("SetFieldBoolValue", BindingFlags.NonPublic | BindingFlags.Instance); mi.Invoke(spfield,new object[]{"CanToggleHidden", true});
you can then set the Hidden property via the OM without getting an exception
spfield.Hidden=true; spfield.Update();
Either way both of these are hacks but at least one is supported.
Powered by: newtelligence dasBlog 2.0.7226.0
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
© Copyright 2012, Colin Byrne
E-mail