When creating content types for WSS and MOSS you quickly hit a problem when trying to define a Lookup column that references itself or another list. This is caused by the fact that the ‘List’ attribute references the unique identifier of the list that it is referencing and not its name.

When I tried to find a solution to this problem I came across a couple of interesting resources. The first was an article by Hristo Pavol called ‘Lookup Fields to the same list‘ in which he posits that you can just provide the value ’self’ to make the column reference the current list. I could not get this to work and so I looked at another solution by Chris O’Brien which he has made available on CodePlex – http://sp2007lookupfields.codeplex.com/ - which is based on his article ‘Creating Lookup columns as a feature‘. This uses the feature activated event of a list that is based on the content type that I had defined.

I tried this solution and managed to get it to work but of course it creates a Site Column and did not add the column to the list which is what I wanted. Using Chris’ code as the basis I came up with the following that finds the list and adds the lookup column that references itself to the list:

    public class PortfolioListFeatureReceiver : SPFeatureReceiver
    {
  
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
                SPWeb currentWeb = null;

                currentWeb = properties.Feature.Parent as SPWeb;

                using (currentWeb)
                {
                    SPList referencedList = currentWeb.Lists["Portfolios"];
                    string columnDefintion = "<Field ID=\"{8D626343-FEBE-438b-B76E-8CEC89EA9A9D}\" Type=\"Lookup\" Name=\"PortfolioParent\" DisplayName=\"Parent\" List=\"{" + referencedList.ID.ToString() + "}\" ShowField=\"LinkTitleNoMenu\" UnlimitedLengthInDocumentLibrary=\"FALSE\" Hidden=\"FALSE\" Required=\"FALSE\" Sealed=\"TRUE\" DisplaceOnUpgrade=\"TRUE\" />";
                    string fieldInternalName = referencedList.Fields.AddFieldAsXml(columnDefintion);
                    SPFieldLookup lookupListField = referencedList.Fields.GetFieldByInternalName(fieldInternalName) as SPFieldLookup;
                    lookupListField.LookupWebId = currentWeb.ID;
                    lookupListField.Update();
                }
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {

        }

        public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        {

        }

        public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        {

        }
    }

This code is placed in a seperate assembly from the one containing your Content Type and List  Definition. As this Assembly needs to go in the GAC it also needs to be Strong named. To associate this Feature Reciever with your list defintion you need to add the RecieverAssembly and RecieiverClass attributes to the Feature element in the feature.xml file for your list definition:

<Feature Id="guid" Title="ListDefinition" Scope="Web" Version="1.0.0.0" Hidden="FALSE" DefaultResourceFile="core" ReceiverAssembly="AssemblyName, Version=Assembly Version, Culture=neutral, PublicKeyToken=Assembly Public Key Token Value, processorArchitecture=MSIL" ReceiverClass="AssemblyName.PortfolioListFeatureReceiver" xmlns="http://schemas.microsoft.com/sharepoint/">
   <ElementManifests>
    ...
  </ElementManifests>
</Feature>

Share:

  • Google Bookmarks
  • Facebook
  • MySpace
  • Twitter
  • del.icio.us
  • Digg
  • Mixx
  • LinkedIn

Add A Comment

Subscribe to Infinite Dreamers