For those who missed my original article (SDK and Microsoft Press Both Wrong?? Custom Fields in the schema.xml
) , you can find it here
I finally got round to posting the code that goes with this article ..
Please find below the details on code for an SPFeatureReceiver class, that will automatically push down changes from your Content Type Features
(you will need to attach the code to your feature using the ReceiverAssembly and ReceiverClass attributes in your feature.
The code needs to be created as a Class in a Class Library, with Microsoft.SharePoint.dll added as a reference, and then added as a Using statement in the class itself.
ContentTypeInstaller : SPFeatureReceiver
// CODE DESCRIPTION
* This is a feature handler which should be paired
* with a content type feature.
* We have identified a problem with Content Types,
* where the content type site columns are not pushed
* down to custom list definitions, until they are
* "modified" first.
* This feature will interrogate all of the associated
* xml files that are attached to the feature.
* Once found, it will "modify" each of the custom fields
* that are referenced.
* This should allow list definitions to use the content
* type columns, without declaring them in the schema.xml
public override void FeatureActivated(SPFeatureReceiverProperties properties)
using(SPSite site = (SPSite)properties.Feature.Parent)
SPWeb web = site.OpenWeb(
// loop through each of the elements in the feature
foreach (SPElementDefinition element in properties.Definition.GetElementDefinitions(CultureInfo.CurrentCulture))
Loop through feature elements
// retrieve the xml content for the feature element
XmlNode content = element.XmlDefinition;
// only continue if the element is a content type definition
if (content.Name == "ContentType")
// grab a new Content Type object
string strCTypeID = content.Attributes["ID"].Value;
SPContentType cType = web.ContentTypes[
Get FieldRef Order from Content type
// grab the original order, we will need this later
string fieldOrder = new string[cType.FieldLinks.Count];
int x = 0;
foreach (SPFieldLink fieldlink in cType.FieldLinks)
fieldOrder[x] = fieldlink.Name;
Add new columns to the content type
// loop through each sub-node in the Content Type file
foreach (XmlNode node in content.ChildNodes)
loop through sub nodes
// only continue for
// the FieldRefs collection
if (node.Name == "FieldRefs")
foreach (XmlNode fieldRef in node.ChildNodes)
Loop through FieldRefs
// only apply for FieldRef tags
if (fieldRef.Name == "FieldRef")
// get the FieldID and use it to
// retrieve the SPField object
string fieldID = fieldRef.Attributes["ID"].Value;
//SPFieldLink fieldLink = cType.FieldLinks[new Guid(fieldID)];
SPField field = cType.Fields[
// first we need to remove the fieldref
// and save, pushing this change down
// NOTE – this will NOT delete any content
// in existing lists!
// now add the field back in again
// and call an update, pushing down all changes
// NOTE – this is what adds the column to those
// lists who don’t already have it.
// reset the field order
// it is possible that adding and
// removing fields would have
// affected this
// force update of the content type,
// pushing down to children
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
public override void FeatureInstalled(SPFeatureReceiverProperties properties)
public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
Enjoy, and happy coding!