Custom Lookup Field Types: migration from 2007 to 2010


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.

Multi Lookup Custom Field Type reverted to Lookup

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:

FLDTYPES_MyCFT.xml

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.

Enforce unique 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.

 


Links to this post

Comments

Thursday, 14 Jul 2011 06:30 by Mark
I've pulled my hair out for a couple of days now trying to get custom properties to work... one broken example after another. Your code works! THANK YOU!!!

Thursday, 8 Sep 2011 11:52 by Tony
Just wanted to thank you for this. I have been very frustrated trying to get SetCustomProperty and GetCustomProperty to work. I worked with SchemaXml directly and was able to get updates to go, but creation of new fields never included my custom property values. I stoed the value on a thread and retrieved it and was able to make that go. But then I read about the built-in methods and thought I would try them. It worked on create but not update! So I have been full circle. Your re-implementation of those methods works great for me. Thank you.

Friday, 9 Mar 2012 01:07 by Davis
Hi, I'm having problem saving multiple values using my custom field (user field type) in a document library. But if its only single value it's saving the user that i choose. Could you please guide me on this. Thanks.

Friday, 9 Mar 2012 08:56 by Steven Van de Craen
Hi Davis, you should seek help on the MSDN Forums (SharePoint development) for this.

CAPTCHA Image Validation