My goal is to have a single click deployment of my intranet site and data.  I have several lists.  Some lists reference other lists through a lookup field.  When I created my list template for the referencing list, I realized that the schema.xml file uses the ID property to identify the field to add to my list.  This is a problem since each time I deploy my site, the ID changes for each list that's being created. 

For this reason, you have to create the lookup field after the list has been created.  My lists are all deployed as features and as part of a larger encompassing WSP.  Since each list is a feature, I have the ability to attach an SPFeatureReceiver class to each feature.  In this feature receiver class, I can handle the activation of a feature by overriding the FeatureActivated method from SPFeatureReceiver.  An event is fired after the feature has been activated.  Subsequently, this method fires off and executes what I need it to.  It is important to note that the feature has already been activated and this method is executed after the list exists on the site. 

 
   1:   
   2:      public class HMBEmployeeListLookupFieldsFeatureReceiver : SPFeatureReceiver
   3:      {
   4:          public override void FeatureActivated(SPFeatureReceiverProperties properties)
   5:          {
   6:              SPWeb web = properties.Feature.Parent as SPWeb;
   7:              if (web == null)
   8:              {
   9:                  SPSite site = properties.Feature.Parent as SPSite;
  10:                  web = site.RootWeb;
  11:              }
  12:              if (web != null)
  13:              {
  14:                  using (web)
  15:                  {
  16:                      SPList employeeList = web.Lists["HMB Employee List"];
  17:                      SPList clientList = web.Lists["HMB Clients"];
  18:                      SPList certList = web.Lists["HMB Certifications"];
  19:                      if (clientList != null && employeeList != null && certList != null)
  20:                      {
  21:                          string primaryClientName = employeeList.Fields.AddLookup("Primary Client", clientList.ID, false);
  22:                          string certificationName = employeeList.Fields.AddLookup("Certifications", certList.ID, false);
  23:                          employeeList.Update();
  24:   
  25:                          SPFieldLookup primaryClient = new SPFieldLookup(employeeList.Fields, primaryClientName);
  26:                          SPFieldLookup certifications = new SPFieldLookup(employeeList.Fields, certificationName);
  27:                          certifications.AllowMultipleValues = true;
  28:                          certifications.Update();
  29:   
  30:                          SPView primaryView = employeeList.DefaultView;
  31:                          if (!primaryView.ViewFields.Exists("Primary Client"))
  32:                          {
  33:                              // retrieve the names of all of the fields used in the view
  34:                              StringCollection viewFields = primaryView.ViewFields.ToStringCollection();
  35:   
  36:                              // remove all of the fields from the view
  37:                              primaryView.ViewFields.DeleteAll();
  38:   
  39:                              // add each of the fields back into the view
  40:                              // while adding the new field at the desired location
  41:                              for (int k = 0; k < viewFields.Count; k++)
  42:                              {
  43:                                  SPField field = new SPField(employeeList.Fields, viewFields[k]);
  44:   
  45:                                  if (k == 1)
  46:                                  {
  47:                                      primaryView.ViewFields.Add(primaryClient);
  48:                                  }
  49:   
  50:                                  if (!field.Id.Equals(primaryClient.Id))
  51:                                  {
  52:                                      primaryView.ViewFields.Add(field);
  53:                                  }
  54:                              }
  55:   
  56:                          }
  57:                          primaryView.Update();
  58:                      }
  59:                  }
  60:              }
  61:          }

Walkthrough:

  • Line 2: Extend SPFeatureReciever
  • Line 4: Override the FeatureActivated Method
  • Line 6-11: Grab the web or site depending on the scope of the feature
  • Line 16-18: Grab the lists that we will be referencing to and from
  • Line 21-22: Grab the two referenced columns from their appropriate lists and add them as lookup fields in the new list.  The "internal" name of the newly created lookup fields are returned from the AddLookup method
  • Line 23: Update the new list
  • Note: you can stop here if you are not going to add them to the default view
  • Line 25-26: Retrieve the actual fields that you added on 21-22
  • Line 27-28: If you want to allow multiple selections of a lookup field, set the appropriate property to true
  • Line 30: Grab the default view from the new list
  • Line 34: transfer the list of fields already in the default view to a string collection for later use
  • Line 37: Remove each field that was originally in the default view
  • Line 41-54: Iterate through the list of fields that were originally in the view.  Add each field back to the view but when you get to the position that you want the new field to exist, add it instead.
  • Line 57: Update the view

It worked for me. 

Technorati Tags: ,