First thing was to create content type based on document library
<ContentType ID="0x010100E9F562320B4441718C2F91D48268EFAD" Name="CustomContentType" Group="Custom Content Types" Description="My Content Type with hidden fields" Inherits="False" V2ListTemplateName="doclib" Version="0"> <FieldRefs> ... <FieldRef ID="{C5E94AC7-EE52-4409-B219-6D6E9B33A172}" Name="MyCustomField" Required="FALSE"/> <FieldRef ID="{B35E5E3C-A0DE-4579-A6C7-D0C83C993A6B}" Name="MyCustomFieldHidden" Required="TRUE" ShowInDisplayForm="FALSE" ShowInEditForm ="TRUE" ShowInListSettings="FALSE" ShowInNewForm="TRUE"/> </FieldRefs> </ContentType>
In next step, I have created event receiver and override ItemUpdating method.
public class CustomFieldEventHandler : SPItemEventReceiver { public override void ItemUpdating(SPItemEventProperties properties) { base.ItemUpdating(properties); IFieldValidator customFieldValidator = new CustomFieldValidator(); if (propertyHasChanged(properties, "MyCustomField")) { checkAndSyncFields(properties, accessGroupFieldValidator, "MyCustomField", "MyCustomFieldHidden"); } else if (propertyHasChanged(properties, "MyCustomFieldHidden")) { checkAndSyncFields(properties, accessGroupFieldValidator, "MyCustomFieldHidden", "MyCustomField"); } }
In ItemUpdating I'm checking if field value has changed, if so, I'm validating it against my rules and updating other field to make sure both have the same value.
Code for checking if field has changed is pretty simple
private bool propertyHasChanged(SPItemEventProperties properties, string fieldName) { string beforeProp = properties.BeforeProperties[fieldName] as string; string afterProp = properties.AfterProperties[fieldName] as string; return string.Compare(beforeProp, afterProp) != 0; }
Validation and synchronization is also fairly simple task in this case.
private void checkAndSyncFields(SPItemEventProperties properties, IFieldValidator fieldValidator, string sourceFieldName, string destFieldName) { string fieldValue = properties.AfterProperties[sourceFieldName] as string; if (!fieldValidator.Validate(fieldValue)) { properties.Status = SPEventReceiverStatus.CancelWithError; properties.ErrorMessage = fieldValidator.GetValidationMessage(sourceFieldName, fieldValue); properties.Cancel = true; } else { properties.AfterProperties.ChangedProperties[destFieldName] = properties.AfterProperties[sourceFieldName]; } }
Validation on EventReceiver level is very nice, since it is working also when list is accessed externally using web services. This way we can assure that only allowed values can be entered into our list.
Last thing to do is to register our Event receiver in our content type
<XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/events"> <spe:Receivers xmlns:spe="http://schemas.microsoft.com/sharepoint/events"> <spe:Receiver> <spe:Name>CustomFieldEventHandler</spe:Name> <spe:Type>ItemUpdating</spe:Type> <spe:Assembly>$SharePoint.Project.AssemblyFullName$</spe:Assembly> <spe:Class>CustomFieldSync.CustomFieldEventHandler</spe:Class> </spe:Receiver> </spe:Receivers> </XmlDocument>
And we are done
Have fun!
No comments:
Post a Comment