Custom Field Types are a rather advanced topic, but very powerful as well. They allow for real integration of custom components inside standard List and Library rendering. (See my other posts on Custom Field Types)
There are some things you can run into. Especially if you have custom Lookup Field Types like Cascading Lookup or Connected Lookup. Here’s what I’ve learned from a recent issue migration one from 2007 to 2010.
Custom Properties
Storing additional information in your Custom Field Types was always a real pain. The mechanism had serious flaws and it required some really dirty programming to work with. So instead I store my custom properties the same way SharePoint does. The involved API is internal but can be exposed through reflection.
I’m adding the this ‘reimplementation’ to every Custom Field Type of mine. When providing a null value to SetCustomProperty, the attribute is removed from the field XML.
1 #region Reimplementation of Get/Set Custom Property 2 public new void SetCustomProperty(string propertyName, object propertyValue) 3 { 4 Type type = typeof(SPField); 5 if (propertyValue != null) 6 { 7 MethodInfo set = type.GetMethod("SetFieldAttributeValue", BindingFlags.NonPublic | BindingFlags.Instance); 8 set.Invoke(this, new object[] { propertyName, propertyValue.ToString() }); 9 } 10 else 11 { 12 MethodInfo remove = type.GetMethod("RemoveFieldAttributeValue", BindingFlags.NonPublic | BindingFlags.Instance); 13 remove.Invoke(this, new object[] { propertyName }); 14 } 15 } 16 public new string GetCustomProperty(string propertyName) 17 { 18 Type type = typeof(SPField); 19 MethodInfo getField = type.GetMethod("GetFieldAttributeValue", BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(String) }, null); 20 object o = getField.Invoke(this, new object[] { propertyName }); 21 return o as String; 22 } 23 #endregion
Now there’s also no more need to predefine custom properties in the FLDTYPES_*.xml either. This applies to any type of Custom Field Type.
AllowMultipleValues
You might see in some cases that when you set the value of SPFieldLookup.AllowMultipleValues to true, your custom field is reverted to a standard Lookup field.
If this is the case, you could override that Property and implement it accordingly.
1 private bool _allowMulti = false; 2 public override bool AllowMultipleValues 3 { 4 get 5 { 6 bool.TryParse(GetCustomProperty("AllowMultipleValues"), out _allowMulti); 7 return _allowMulti; 8 } 9 set 10 { 11 if (this.AllowMultipleValues != value) 12 { 13 _allowMulti = value; 14 SetCustomProperty("AllowMultipleValues", _allowMulti.ToString()); 15 if (value) 16 { 17 SetCustomProperty("Mult", "TRUE"); 18 SetCustomProperty("Sortable", "FALSE"); 19 } 20 else 21 { 22 SetCustomProperty("Mult", "FALSE"); 23 SetCustomProperty("Sortable", "TRUE"); 24 } 25 } 26 } 27 }
This applies to custom Multi Lookup Field Types.
Note: could not reproduce the issue with a new custom lookup field type in a clean SharePoint 2010 environment…
AllowBaseTypeRendering
We’ve seen this issue in a recent migration from SharePoint 2007 to SharePoint 2010 for a custom developed Connected Lookup Field (Single and Multi Valued). The field was ported from SharePoint 2007 with the following FLDTYPES_*.xml configuration:
The AllowBaseTypeRendering attribute will default to the rendering of the Base Type (in this case Lookup) when the Custom Field Type cannot be determined.
This had the weird effect that these fields would not render or store *any* value selected in a Multi Valued Field of this type. This behaviour might only be occuring when there’s a custom RenderPattern defined for the Custom Field Type.
In either way we had to remove the attribute for SharePoint 2010, since we really required the RenderPattern. Problem solved for new fields, but there was still an issue for existing fields (existing SharePoint 2007 content migrated to SharePoint 2010).
For those existing fields, we wrote a script that would remove the attribute causing the problem:
1 SPList list = web.GetList(listUrl); 2 SPField field = list.Fields["MyMULTI"]; 3 MyField clf = field as MyField; 4 clf.SetCustomProperty("BaseRenderingType", null); 5 clf.Update();
This is where the custom SetCustomProperty came in handy for removing the BaseRenderingType attribute (added because the Custom Field Type had the AllowBaseTypeRendering attribute).
In our case we knew exactly where the fields were that had our Custom Field Type, but it might be more difficult to write a generic script to find all fields based on the Custom Field Type…
Note: could not reproduce the issue with a new custom lookup field type in a clean SharePoint 2010 environment…
Enforce unique values
You can force unique values on fields in SharePoint 2010, however is is not compatible when storing multiple values.
If this is the case your custom “edit field control” should disable the option to “Enforce unique values” via JavaScript.
Oh, and for those wondering: you still can’t do cross site collection lookups with a lookup field. Which makes me wonder how that works in regard to the Content Type Hub.