+ Start a Discussion
HeatherTHeatherT 

Dependant Picklist Values in C#

Does anyone have any sample code on how to pull dependant picklist values using C#?  My code for the DescribeSObjectResult and my loop through the fields and picklist values works perfectly...I am stuck trying to determine which picklist values are valid for which values on the controlling picklist field.
 
Thanks.
BillHansonBillHanson
The problem with accessing dependent picklists is the way they are stored in the schema.  Each dependent picklist entry has a property called "validFor" which is a bitset where each bit indicates whether the value is valid for that bit's position in the controller field's options array.  So if bit 0 is set, then the value is valid if the first choice is selected in the controller field, if bit 1 is set, then the value is valid if the second choice is selected in the controller field, etc...

Here is an example from a class that I use to get dependent picklist values into a readable XML representation.  It uses a helper class called Bitset (posted below) that does the work of breaking the validFor property down into an array or bits.  Arguments: picklistEntry is the entry to test, parentField is the entry's field, and strObjectType is the name of the object that contains the field.  Utility.GetField is a helper function that returns a field definition using describeSObject.

      private string GetValidForNodes(SforceReference.PicklistEntry picklistEntry, SforceReference.Field parentField, String strObjectType)
      {
         String strResult = "";

         // Get the controller field by name.
         if (!parentField.dependentPicklist) return "";
         if (parentField.controllerName == "") return "";
         SforceReference.Field controller = Utility.GetField(strObjectType, parentField.controllerName);

         // For each PicklistEntry get all controlling values for which it is valid.
         Bitset validFor = new Bitset(picklistEntry.validFor);
         if (validFor.size() == 0) return "";
         if (controller.type.ToString() == "picklist")
         {
            // The controller is a picklist.  Get all controlling values for which this entry is valid.
            for (int i = 0; i < validFor.size(); i++)
            {
               if (validFor.testBit(i))
               {
                  // Since the bit is set, this entry is valid for the controlling entry at index i.
                  strResult += "\t\t\t\t\t<dependentValue>\r\n";
                  strResult += "\t\t\t\t\t\t<value>" + Utility.XmlEncode(controller.picklistValues[i].value) + "</value>\r\n";
                  strResult += "\t\t\t\t\t\t<label>" + Utility.XmlEncode(controller.picklistValues[i].label) + "</label>\r\n";
                  strResult += "\t\t\t\t\t</dependentValue>\r\n";
               }
            }
         }
         else if (controller.type.ToString() == "boolean")
         {
            // The controller is a checkbox.

            // If bit 0 is set this entry is valid if the controller is not checked.
            if (validFor.testBit(0)) strResult += "\t\t\t\t\t<dependentValue>unchecked</dependentValue>\r\n";

            // If bit 1 is set this entry is valid if the controller is checked.
            if (validFor.testBit(1)) strResult += "\t\t\t\t\t<dependentValue>checked</dependentValue>\r\n";
         }

         return strResult;
      }


   class Bitset
   {
      // helper class to decode a "validFor" bitset class Bitset
      byte[] data;
      public Bitset(byte[] data)
      {
         this.data = data == null ? new byte[0] : data;
      }
      public bool testBit(int n)
      {
         return (data[n >> 3] & (0x80 >> n % 8)) != 0;
      }
      public int size()
      {
         return data.Length * 8;
      }
   }

BillHansonBillHanson
Sorry, I didn't use the SRC tool.  Here's a re-post of the source code:

Code:
  private string GetValidForNodes(SforceReference.PicklistEntry picklistEntry, SforceReference.Field parentField, String strObjectType)
  {
   String strResult = "";

   // Get the controller field by name.
   if (!parentField.dependentPicklist) return "";
   if (parentField.controllerName == "") return "";
   SforceReference.Field controller = Utility.GetField(strObjectType, parentField.controllerName);

   // For each PicklistEntry get all controlling values for which it is valid.
   Bitset validFor = new Bitset(picklistEntry.validFor);
   if (validFor.size() == 0) return "";
   if (controller.type.ToString() == "picklist")
   {
    // The controller is a picklist.  Get all controlling values for which this entry is valid.
    for (int i = 0; i < validFor.size(); i++)
    {
     if (validFor.testBit(i))
     {
      // Since the bit is set, this entry is valid for the controlling entry at index i.
      strResult += "\t\t\t\t\t<dependentValue>\r\n";
      strResult += "\t\t\t\t\t\t<value>" + Utility.XmlEncode(controller.picklistValues[i].value) + "</value>\r\n";
      strResult += "\t\t\t\t\t\t<label>" + Utility.XmlEncode(controller.picklistValues[i].label) + "</label>\r\n";
      strResult += "\t\t\t\t\t</dependentValue>\r\n";
     }
    }
   }
   else if (controller.type.ToString() == "boolean")
   {
    // The controller is a checkbox.

    // If bit 0 is set this entry is valid if the controller is not checked.
    if (validFor.testBit(0)) strResult += "\t\t\t\t\t<dependentValue>unchecked</dependentValue>\r\n";

    // If bit 1 is set this entry is valid if the controller is checked.
    if (validFor.testBit(1)) strResult += "\t\t\t\t\t<dependentValue>checked</dependentValue>\r\n";
   }

   return strResult;
  }
Code:
 class Bitset
 {
  // helper class to decode a "validFor" bitset class Bitset
  byte[] data;
  public Bitset(byte[] data)
  {
   this.data = data == null — new byte[0] : data;
  }
  public bool testBit(int n)
  {
   return (data[n >> 3] & (0x80 >> n % 8)) != 0;
  }
  public int size()
  {
   return data.Length * 8;
  }
 }