I'm trying to do some script validation in a tool I wrote. The user first selects a dataframe from the current mxd. This parameter works fine. When the user makes this selection, the next parameter, a list of layers in that dataframe should populate the next parameter. But all I get with the code below is an empty list. I can get layers for the entire mxd, but am unable to restrict it to the selected dataframe. This seems like something simple I'm missing. How can I accomplish this?
def initializeParameters(self):
"""Refine the properties of a tool's parameters. This method is
called when the tool is opened.
Populates data frame parameter with data frames in map and disables other
parameters.
"""
try: # this works
mxd = arcpy.mapping.MapDocument('CURRENT')
dflist = [df.name for df in arcpy.mapping.ListDataFrames(mxd)]
self.params[0].filter.type = "ValueList"
self.params[0].filter.list = dflist
del mxd
except:
arcpy.AddError("\nMust run this tool in ArcMap, not ArcCatalog")
self.params[1].enabled = False
self.params[2].enabled = False
return
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."""
mxd = arcpy.mapping.MapDocument('CURRENT')
if self.params[0].value:
self.params[1].enabled = True
# this does not work the way I want
layerList = [lyr.name for lyr in arcpy.mapping.ListLayers(mxd, self.params[0].value) if not lyr.isGroupLayer]
uniqueList = list(set(layerList))
uniqueList.sort()
self.params[1].filter.type = "ValueList"
self.params[1].filter.list = uniqueList
1 Answer 1
I think this line is wrong:
layerList = [lyr.name for lyr in arcpy.mapping.ListLayers(mxd, self.params[0].value) if not lyr.isGroupLayer]
A ListLayers()
requires an mxd
or a dataframe
, not both. So should be
layerList = [lyr.name for lyr in arcpy.mapping.ListLayers(self.params[0].value) if not lyr.isGroupLayer]
Here is the entire updateParameters(self)
function that worked for me. I had to get the Data Frame using arcpy.mapping.ListDataFrames()
and then use that in the arcpy.mapping.ListLayers()
.
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."""
mxd = arcpy.mapping.MapDocument('CURRENT')
if self.params[0].value:
self.params[1].enabled = True
df = arcpy.mapping.ListDataFrames(mxd, self.params[0].value)[0]
if df:
layerList = [lyr.name for lyr in arcpy.mapping.ListLayers(df) if not lyr.isGroupLayer]
uniqueList = list(set(layerList))
uniqueList.sort()
self.params[1].filter.list = uniqueList
Selecting the first Dataframe gives a list of the layers in that frame:
enter image description here
Selecting the second Dataframe then shows the list of those layers:
enter image description here
Note that if you select your dataframe, and then a layer, but then decide to change the dataframe you may see an error. This is just telling you that the currently selected layer is not in the list of layers. Selecting a valid layer will remove the error. There is probably a way to get around that error, but I didn't find it in my brief look.
Explore related questions
See similar questions with these tags.