Cascading Dropdown

12-04-2013 06:45 AM
New Contributor
Im still fairly new to pyhton scripting in Arcmap and the whole scripting process.
I have made a scripting tool that is made to help the user to navigate to an address on a map. what i need to do though is make it easier by settign up the parameters in a neater way. Right now the way its set is it is the paramters are drop down list of all possible options but i want to set it up so that if i choos from parameter 1 a certain street name, in parameter 2 it will only give me street types that match with that street name.
Tags (2)
0 Kudos
3 Replies
Occasional Contributor II
Are you doing this through a normal script tool (like in a toolbox) or through an add-in tool?

In the first case, you could modify the validation code (right-click the script tool, properties, validation tab) so that when the first parameter is altered, you use the value to filter the list of the next parameter.

Example of some validation code I modified. Have to fill in the first parameter, database connection, first (everything else is disabled). Once it's been entered, the connection is used to path to a feature class and derive a picklist from one of its fields. The script then enables the other parameters.

 # validation code
 # Feb 2012 msayler
 # Updated Jul 2012
 # Must be copied into the script tool's validation code 
 # in the Validation tab under Properties
class ToolValidator:
 """Class for validating a tool's parameter values and controlling
 the behavior of the tool's dialog."""

 def __init__(self):
  """Setup the Geoprocessor and the list of tool parameters."""
  import arcpy
  self.params = arcpy.GetParameterInfo()
  self.X = 0
  self.fcfield = (None,None)

 def initializeParameters(self):
  """Refine the properties of a tool's parameters.  This method is
  called when the tool is opened."""
  self.params[1].enabled = False
  self.params[2].enabled = False
  #self.params[3].Value = self.X #for debugging

 def updateParameters(self):
  """Modify the values and properties of parameters before internal
  validation is performed.  This method is called whenever a parameter
  has been changed."""
  if self.X == 0:
   if self.params[0].altered == True:
    FC = str(self.params[0].value) + "\\gis2.ELEC.ElectricDataset\\gis2.ELEC.eCircuitBreaker"
    Col = "FeederID"
    self.fcfield = (FC, Col)
    self.params[1].filter.list = [str(val) for val in \
              row.getValue(Col) for row in \
               arcpy.SearchCursor(FC, None, None, Col)\
    self.params[1].enabled = True
    self.params[2].enabled = True
    self.X = 1
   #self.params[3].value = self.X #for debugging
  # if self.params[1].Value not in self.params[1].filter.list:
   # self.params[1].Value = self.params[1].filter.list[0]

 def updateMessages(self):
  """Modify the messages created by internal validation for each tool
  parameter.  This method is called after internal validation."""

For the second case, I haven't worked with add-ins yet, but I think you could do a similar sort of process. Catch that the field has changed, then use the value it changed to to calculate the choices for the next one.
0 Kudos
Occasional Contributor II
What you are talking about is definitely possible with a tool validator. How you would go about it depends on if you have written the tool as a script that you reference in a toolbox (.py extension) or as a python toolbox (.pyt extension).

In a .pyt toolbox I use the following to make sure that two parameters never reference the same field:

def updateParameters(self, parameters):
    '''Modify the values and properties of parameters before internal
    validation is performed.  This method is called whenever a parameter
    has been changed.'''
    #Need to make sure that the additional fields option ONLY lists fields
    #that will not be standardized.
    if parameters[0].value:
        old_fields = [ for field in arcpy.ListFields(parameters[0].value)]
        if parameters[1].altered:
            if parameters[1].valueAsText in old_fields:
        if parameters[2].altered:
            if parameters[2].valueAsText in old_fields:
        parameters[3].filter.list = old_fields

The syntax would be similar to this in the tool validator if you are using a .py file. There is some more discussion in this thread about using tool validators.

Hope this helps,
- Doug
0 Kudos
New Contributor
OK thank you for your help i was able to find the way to properly set it up in the tool Validator
What i needed to end up doing was in the update paramameter
query = ('"ST_NAME"='+"'"+str(self.params[1].value)+"'")
self.params[2].filter.list = [str(val) for val in
                                        row.getValue(col) for row in
0 Kudos