Working with Dependent Picklists
The following code can be used as a basis for a utility class that returns the metadata for a controller and dependent picklist:
public class DependentField { /// <summary> /// Dictionary of Lists of strings containing dependent values with the keys of the controlling field values /// </summary> /// <param name="sObject">API name of the SObject</param> /// <param name="controllingFieldName">API name of the controlling picklist</param> /// <param name="dependentFieldName">API name of the dependent picklist</param> public static Dictionary<string, List<string>> GetControllingAndDependentPicklistValues(string sObject, string controllingFieldName, string dependentFieldName) { Dictionary<string, List<string>> dependencies = new Dictionary<string, List<string>>(); SalesforceSession salesforceSession = SessionTest.GetActiveSession(); DescribeSObjectResult describeSObjectResult = salesforceSession.Binding.describeSObjectCached(sObject); Field controllingField = describeSObjectResult.fields.ToList().Single(f => f.name == controllingFieldName); Field dependentField = describeSObjectResult.fields.ToList().Single(f => f.name == dependentFieldName); //confirm everything is set up properly Debug.Assert(controllingField.type == fieldType.picklist, "Controlling field needs to be a picklist"); Debug.Assert(dependentField.type == fieldType.picklist, "Dependent field needs to be a picklist"); Debug.Assert(dependentField.dependentPicklist, "Dependent field needs to be a dependent picklist"); Debug.Assert(dependentField.controllerName == controllingFieldName, "Dependent field controlling field name needs to be " + controllingFieldName); for (int i = 0; i < dependentField.picklistValues.Length; i++) { Bitset validFor = new Bitset(dependentField.picklistValues[i].validFor); for (int k = 0; k < validFor.size(); k++) { if (validFor.testBit(k)) { string value = controllingField.picklistValues[k].label; List<string> values; if (dependencies.TryGetValue(value, out values)) { if (!values.Contains(value)) { values.Add(dependentField.picklistValues[i].value); } } else { values = new List<string>(); values.Add(dependentField.picklistValues[i].value); dependencies.Add(value, values); } } } } return dependencies; } /// <summary> /// Inner class to decode a "validFor" bitset /// </summary> 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; } } }
Usage
In the following example, the controlling picklist Beverage has two values, which relate to the values of the dependent picklist Beverage Variety on the Product2 SObject:
Beverage | Beverage Variety |
---|---|
Coffee | Decaffeinated |
Regular | |
Tea | Chamomile |
Earl Grey | |
English Breakfast |
To get the Dictionary of controlling and dependent field values, execute the following code for the class above:
Dictionary<string, List<string>> dependentPicklistValues = DependantField.GetControllingAndDependentPicklistValues(Product2.SFType, "Beverage__c", "Beverage_Variety__c");
This will return a dictionary with the string keys "Coffee" and "Tea" along with string Lists containing their respective dependent values.
More information can be found here: https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_describesobjects_describesobjectresult.htm#about_dep_picklist