Using two Python Addin Combo Boxes to choose feature class first then field from chosen feature class?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
2
down vote

favorite
1












Last night a student from my Udemy course about writing Python AddIns asked for:




some tips for using a combo box to filter another combo box. What I am
trying to do is use a combo box to select my [feature class], which I've managed
to do. Once that combo box is selected, I want the second box to show
all the fields in that [feature class], which I can then go ahead and select to
perform further analysis on.




I think the key to doing this may be found in code from @sur's answer (with help from Freddie Gibson of Esri) to Dynamically adding items into one python addin Combobox from another?:



import arcpy
import pythonaddins

class ComboBoxClass1(object):
"""Implementation for TestCombo_addin.combobox (ComboBox)"""
def __init__(self):
self.items = ["cb1item1", "cb1item2"]
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWW'
self.width = 'WWWWWW'
ComboBoxClass1._hook=self
def onSelChange(self, selection):
pass

class ComboBoxClass2(object):
"""Implementation for TestCombo_addin.combobox_1 (ComboBox)"""
def __init__(self):
self.items = ["cb2item1", "cb2item2"]
self.editable = True
self.enabled = True
self.dropdownWidth = 'WWWWWW'
self.width = 'WWWWWW'
def onSelChange(self, selection):
ComboBoxClass1._hook.items.append(selection)


but how do I use the _hook property of a ComboBoxClass to achieve what my student has asked for?










share|improve this question



























    up vote
    2
    down vote

    favorite
    1












    Last night a student from my Udemy course about writing Python AddIns asked for:




    some tips for using a combo box to filter another combo box. What I am
    trying to do is use a combo box to select my [feature class], which I've managed
    to do. Once that combo box is selected, I want the second box to show
    all the fields in that [feature class], which I can then go ahead and select to
    perform further analysis on.




    I think the key to doing this may be found in code from @sur's answer (with help from Freddie Gibson of Esri) to Dynamically adding items into one python addin Combobox from another?:



    import arcpy
    import pythonaddins

    class ComboBoxClass1(object):
    """Implementation for TestCombo_addin.combobox (ComboBox)"""
    def __init__(self):
    self.items = ["cb1item1", "cb1item2"]
    self.editable = True
    self.enabled = True
    self.dropdownWidth = 'WWWWWW'
    self.width = 'WWWWWW'
    ComboBoxClass1._hook=self
    def onSelChange(self, selection):
    pass

    class ComboBoxClass2(object):
    """Implementation for TestCombo_addin.combobox_1 (ComboBox)"""
    def __init__(self):
    self.items = ["cb2item1", "cb2item2"]
    self.editable = True
    self.enabled = True
    self.dropdownWidth = 'WWWWWW'
    self.width = 'WWWWWW'
    def onSelChange(self, selection):
    ComboBoxClass1._hook.items.append(selection)


    but how do I use the _hook property of a ComboBoxClass to achieve what my student has asked for?










    share|improve this question

























      up vote
      2
      down vote

      favorite
      1









      up vote
      2
      down vote

      favorite
      1






      1





      Last night a student from my Udemy course about writing Python AddIns asked for:




      some tips for using a combo box to filter another combo box. What I am
      trying to do is use a combo box to select my [feature class], which I've managed
      to do. Once that combo box is selected, I want the second box to show
      all the fields in that [feature class], which I can then go ahead and select to
      perform further analysis on.




      I think the key to doing this may be found in code from @sur's answer (with help from Freddie Gibson of Esri) to Dynamically adding items into one python addin Combobox from another?:



      import arcpy
      import pythonaddins

      class ComboBoxClass1(object):
      """Implementation for TestCombo_addin.combobox (ComboBox)"""
      def __init__(self):
      self.items = ["cb1item1", "cb1item2"]
      self.editable = True
      self.enabled = True
      self.dropdownWidth = 'WWWWWW'
      self.width = 'WWWWWW'
      ComboBoxClass1._hook=self
      def onSelChange(self, selection):
      pass

      class ComboBoxClass2(object):
      """Implementation for TestCombo_addin.combobox_1 (ComboBox)"""
      def __init__(self):
      self.items = ["cb2item1", "cb2item2"]
      self.editable = True
      self.enabled = True
      self.dropdownWidth = 'WWWWWW'
      self.width = 'WWWWWW'
      def onSelChange(self, selection):
      ComboBoxClass1._hook.items.append(selection)


      but how do I use the _hook property of a ComboBoxClass to achieve what my student has asked for?










      share|improve this question















      Last night a student from my Udemy course about writing Python AddIns asked for:




      some tips for using a combo box to filter another combo box. What I am
      trying to do is use a combo box to select my [feature class], which I've managed
      to do. Once that combo box is selected, I want the second box to show
      all the fields in that [feature class], which I can then go ahead and select to
      perform further analysis on.




      I think the key to doing this may be found in code from @sur's answer (with help from Freddie Gibson of Esri) to Dynamically adding items into one python addin Combobox from another?:



      import arcpy
      import pythonaddins

      class ComboBoxClass1(object):
      """Implementation for TestCombo_addin.combobox (ComboBox)"""
      def __init__(self):
      self.items = ["cb1item1", "cb1item2"]
      self.editable = True
      self.enabled = True
      self.dropdownWidth = 'WWWWWW'
      self.width = 'WWWWWW'
      ComboBoxClass1._hook=self
      def onSelChange(self, selection):
      pass

      class ComboBoxClass2(object):
      """Implementation for TestCombo_addin.combobox_1 (ComboBox)"""
      def __init__(self):
      self.items = ["cb2item1", "cb2item2"]
      self.editable = True
      self.enabled = True
      self.dropdownWidth = 'WWWWWW'
      self.width = 'WWWWWW'
      def onSelChange(self, selection):
      ComboBoxClass1._hook.items.append(selection)


      but how do I use the _hook property of a ComboBoxClass to achieve what my student has asked for?







      arcpy python-addin combo-box






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 5 hours ago

























      asked 5 hours ago









      PolyGeo♦

      52.3k1779236




      52.3k1779236




















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          2
          down vote













          The code that I used to solve this was:



          import arcpy
          import pythonaddins

          class ComboBoxClass1(object):
          """Implementation for ComboBox_addin.combobox1 (ComboBox)"""
          def __init__(self):
          arcpy.env.workspace = r"C:polygeoQGIS"
          self.items = arcpy.ListFeatureClasses()
          self.editable = True
          self.enabled = True
          self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
          self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
          def onSelChange(self, selection):
          ComboBoxClass2._hook.items = [x.name for x in arcpy.ListFields(selection)]
          def onEditChange(self, text):
          pass
          def onFocus(self, focused):
          pass
          def onEnter(self):
          pass
          def refresh(self):
          pass

          class ComboBoxClass2(object):
          """Implementation for ComboBox_addin.combobox2 (ComboBox)"""
          def __init__(self):
          self.items =
          self.editable = True
          self.enabled = True
          self.dropdownWidth = 'WWWWWWWWWWWW'
          self.width = 'WWWWWWWWWWWW'
          ComboBoxClass2._hook=self
          def onSelChange(self, selection):
          pass
          def onEditChange(self, text):
          pass
          def onFocus(self, focused):
          pass
          def onEnter(self):
          pass
          def refresh(self):
          pass


          To understand the code:



          • when initializing the first combo box I set its items to be all the feature classes in a workspace that I set. Since that workspace is a folder this results in a list of shapefiles that gets presented to me as a pulldown.

          • when initializing the second combo box I set its items to be an empty list and I also provide a hook (which seems to be an arbitrary property that could be named anything) to that list using ComboBoxClass2._hook=self

          • when I choose a shapefile from the first combo box its onSelChange function takes my selection and uses that to set the items in my hook to the second combo box to be the fields from the shapefile that I choose. Since ListFields returns a list of field objects I use list comprehension to turn that into a list of field names instead.

          enter image description here



          enter image description here






          share|improve this answer






















          • I'm currently doing something similar but using global variables instead of a Class._hook. I think I like the way you've done it better. But could you please explain the ._hook a bit further. Ie, is _hook just an arbitrarily named class property that you made up, or is it a built-in Python name?
            – Son of a Beach
            5 hours ago











          • @SonofaBeach I've not seen any documentation on it, the only source for it being available came from the earlier Q&A that I linked to in the question. I'm not enough of a Pythonista to be sure but I think it must be a property that either ArcPy or Python provides.
            – PolyGeo♦
            5 hours ago










          • What happens if you replace ._hook with something arbitrary like, .sharedInstance? (If you have a chance to try it out.) I can't find any documentation on _hook, and the only examples I can find for it make it look like it's just an arbitrary property.
            – Son of a Beach
            4 hours ago











          • @SonofaBeach You're right. I replaced ._hook with .sharedInstance and it worked just the same.
            – PolyGeo♦
            4 hours ago











          • Hey, thanks for trying this out. Looks like it's just a simple class attribute, which makes sense. I might go and update my own Add-In now to use a similar strategy instead of the global variables I'm currently using.
            – Son of a Beach
            4 hours ago

















          up vote
          0
          down vote













          I think setting a hook to a class instance to be accessed through a class property (as opposed to a property of an instance of that class) is bad practice and while it works fine here will cause you grief if you use this construct in other code. E.g. you write a class and create more than one instance of it or you have a superclass with this hook and you create multiple subclasses or multiple instances of a subclass. The hook property of the class will get overwritten each time an instance is created.



          What I do is use the instances of the classes, not the classes themselves.



          For example, in config.xml you will have something like:



          <?xml version="1.0"?>
          <ESRI.Configuration etc...>
          <etc...>
          <AddIn language="PYTHON" library="ComboBox_addin.py" namespace="ComboBox_addin">
          <ArcMap>
          <Commands>
          <ComboBox caption="CB1" category="Blah" class="ComboBoxClass1" id="ComboBox_addin.combobox1" etc...>etc...</ComboBox>
          <ComboBox caption="CB2" category="Blah" class="ComboBoxClass2" id="ComboBox_addin.combobox2" etc...>etc...</ComboBox>
          </Commands>
          <Extensions></Extensions>
          <Toolbars>
          <Toolbar caption="Blah blah" category="Blah" id="ComboBox_addin.toolbar" showInitially="true">
          <Items>
          <ComboBox refID="ComboBox_addin.combobox1"/>
          <ComboBox refID="ComboBox_addin.combobox2"/>
          </Items>
          </Toolbar>
          </Toolbars>
          <Menus></Menus>
          </ArcMap>
          </AddIn>
          </ESRI.Configuration>


          Note the id and refID are the same. These will refer to instances of these classes.



          Then you just replace references to ComboBoxClass2 to combobox2 in your code:



          import arcpy
          import pythonaddins

          class ComboBoxClass1(object):
          """Implementation for ComboBox_addin.combobox1 (ComboBox)"""
          def __init__(self):
          arcpy.env.workspace = r"C:polygeoQGIS"
          self.items = arcpy.ListFeatureClasses()
          self.editable = True
          self.enabled = True
          self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
          self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
          def onSelChange(self, selection):
          combobox2.items = [x.name for x in arcpy.ListFields(selection)] # <================
          def onEditChange(self, text):
          pass
          def onFocus(self, focused):
          pass
          def onEnter(self):
          pass
          def refresh(self):
          pass

          class ComboBoxClass2(object):
          """Implementation for ComboBox_addin.combobox2 (ComboBox)"""
          def __init__(self):
          self.items =
          self.editable = True
          self.enabled = True
          self.dropdownWidth = 'WWWWWWWWWWWW'
          self.width = 'WWWWWWWWWWWW'

          def onSelChange(self, selection):
          pass
          def onEditChange(self, text):
          pass
          def onFocus(self, focused):
          pass
          def onEnter(self):
          pass
          def refresh(self):
          pass


          If you run into a NameError (an issue with earlier ArcGIS versions, not sure if still a problem), put the following at the bottom of ComboBox_addin.py:
          :



          ##Workaround for 'NameError: global name 'combobox2' is not defined' - https://geonet.esri.com/thread/76833
          combobox1 = ComboBoxClass1()
          combobox2 = ComboBoxClass2()





          share|improve this answer






















            Your Answer








            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "79"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "",
            contentPolicyHtml: "",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fgis.stackexchange.com%2fquestions%2f300756%2fusing-two-python-addin-combo-boxes-to-choose-feature-class-first-then-field-from%23new-answer', 'question_page');

            );

            Post as a guest






























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            2
            down vote













            The code that I used to solve this was:



            import arcpy
            import pythonaddins

            class ComboBoxClass1(object):
            """Implementation for ComboBox_addin.combobox1 (ComboBox)"""
            def __init__(self):
            arcpy.env.workspace = r"C:polygeoQGIS"
            self.items = arcpy.ListFeatureClasses()
            self.editable = True
            self.enabled = True
            self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
            self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
            def onSelChange(self, selection):
            ComboBoxClass2._hook.items = [x.name for x in arcpy.ListFields(selection)]
            def onEditChange(self, text):
            pass
            def onFocus(self, focused):
            pass
            def onEnter(self):
            pass
            def refresh(self):
            pass

            class ComboBoxClass2(object):
            """Implementation for ComboBox_addin.combobox2 (ComboBox)"""
            def __init__(self):
            self.items =
            self.editable = True
            self.enabled = True
            self.dropdownWidth = 'WWWWWWWWWWWW'
            self.width = 'WWWWWWWWWWWW'
            ComboBoxClass2._hook=self
            def onSelChange(self, selection):
            pass
            def onEditChange(self, text):
            pass
            def onFocus(self, focused):
            pass
            def onEnter(self):
            pass
            def refresh(self):
            pass


            To understand the code:



            • when initializing the first combo box I set its items to be all the feature classes in a workspace that I set. Since that workspace is a folder this results in a list of shapefiles that gets presented to me as a pulldown.

            • when initializing the second combo box I set its items to be an empty list and I also provide a hook (which seems to be an arbitrary property that could be named anything) to that list using ComboBoxClass2._hook=self

            • when I choose a shapefile from the first combo box its onSelChange function takes my selection and uses that to set the items in my hook to the second combo box to be the fields from the shapefile that I choose. Since ListFields returns a list of field objects I use list comprehension to turn that into a list of field names instead.

            enter image description here



            enter image description here






            share|improve this answer






















            • I'm currently doing something similar but using global variables instead of a Class._hook. I think I like the way you've done it better. But could you please explain the ._hook a bit further. Ie, is _hook just an arbitrarily named class property that you made up, or is it a built-in Python name?
              – Son of a Beach
              5 hours ago











            • @SonofaBeach I've not seen any documentation on it, the only source for it being available came from the earlier Q&A that I linked to in the question. I'm not enough of a Pythonista to be sure but I think it must be a property that either ArcPy or Python provides.
              – PolyGeo♦
              5 hours ago










            • What happens if you replace ._hook with something arbitrary like, .sharedInstance? (If you have a chance to try it out.) I can't find any documentation on _hook, and the only examples I can find for it make it look like it's just an arbitrary property.
              – Son of a Beach
              4 hours ago











            • @SonofaBeach You're right. I replaced ._hook with .sharedInstance and it worked just the same.
              – PolyGeo♦
              4 hours ago











            • Hey, thanks for trying this out. Looks like it's just a simple class attribute, which makes sense. I might go and update my own Add-In now to use a similar strategy instead of the global variables I'm currently using.
              – Son of a Beach
              4 hours ago














            up vote
            2
            down vote













            The code that I used to solve this was:



            import arcpy
            import pythonaddins

            class ComboBoxClass1(object):
            """Implementation for ComboBox_addin.combobox1 (ComboBox)"""
            def __init__(self):
            arcpy.env.workspace = r"C:polygeoQGIS"
            self.items = arcpy.ListFeatureClasses()
            self.editable = True
            self.enabled = True
            self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
            self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
            def onSelChange(self, selection):
            ComboBoxClass2._hook.items = [x.name for x in arcpy.ListFields(selection)]
            def onEditChange(self, text):
            pass
            def onFocus(self, focused):
            pass
            def onEnter(self):
            pass
            def refresh(self):
            pass

            class ComboBoxClass2(object):
            """Implementation for ComboBox_addin.combobox2 (ComboBox)"""
            def __init__(self):
            self.items =
            self.editable = True
            self.enabled = True
            self.dropdownWidth = 'WWWWWWWWWWWW'
            self.width = 'WWWWWWWWWWWW'
            ComboBoxClass2._hook=self
            def onSelChange(self, selection):
            pass
            def onEditChange(self, text):
            pass
            def onFocus(self, focused):
            pass
            def onEnter(self):
            pass
            def refresh(self):
            pass


            To understand the code:



            • when initializing the first combo box I set its items to be all the feature classes in a workspace that I set. Since that workspace is a folder this results in a list of shapefiles that gets presented to me as a pulldown.

            • when initializing the second combo box I set its items to be an empty list and I also provide a hook (which seems to be an arbitrary property that could be named anything) to that list using ComboBoxClass2._hook=self

            • when I choose a shapefile from the first combo box its onSelChange function takes my selection and uses that to set the items in my hook to the second combo box to be the fields from the shapefile that I choose. Since ListFields returns a list of field objects I use list comprehension to turn that into a list of field names instead.

            enter image description here



            enter image description here






            share|improve this answer






















            • I'm currently doing something similar but using global variables instead of a Class._hook. I think I like the way you've done it better. But could you please explain the ._hook a bit further. Ie, is _hook just an arbitrarily named class property that you made up, or is it a built-in Python name?
              – Son of a Beach
              5 hours ago











            • @SonofaBeach I've not seen any documentation on it, the only source for it being available came from the earlier Q&A that I linked to in the question. I'm not enough of a Pythonista to be sure but I think it must be a property that either ArcPy or Python provides.
              – PolyGeo♦
              5 hours ago










            • What happens if you replace ._hook with something arbitrary like, .sharedInstance? (If you have a chance to try it out.) I can't find any documentation on _hook, and the only examples I can find for it make it look like it's just an arbitrary property.
              – Son of a Beach
              4 hours ago











            • @SonofaBeach You're right. I replaced ._hook with .sharedInstance and it worked just the same.
              – PolyGeo♦
              4 hours ago











            • Hey, thanks for trying this out. Looks like it's just a simple class attribute, which makes sense. I might go and update my own Add-In now to use a similar strategy instead of the global variables I'm currently using.
              – Son of a Beach
              4 hours ago












            up vote
            2
            down vote










            up vote
            2
            down vote









            The code that I used to solve this was:



            import arcpy
            import pythonaddins

            class ComboBoxClass1(object):
            """Implementation for ComboBox_addin.combobox1 (ComboBox)"""
            def __init__(self):
            arcpy.env.workspace = r"C:polygeoQGIS"
            self.items = arcpy.ListFeatureClasses()
            self.editable = True
            self.enabled = True
            self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
            self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
            def onSelChange(self, selection):
            ComboBoxClass2._hook.items = [x.name for x in arcpy.ListFields(selection)]
            def onEditChange(self, text):
            pass
            def onFocus(self, focused):
            pass
            def onEnter(self):
            pass
            def refresh(self):
            pass

            class ComboBoxClass2(object):
            """Implementation for ComboBox_addin.combobox2 (ComboBox)"""
            def __init__(self):
            self.items =
            self.editable = True
            self.enabled = True
            self.dropdownWidth = 'WWWWWWWWWWWW'
            self.width = 'WWWWWWWWWWWW'
            ComboBoxClass2._hook=self
            def onSelChange(self, selection):
            pass
            def onEditChange(self, text):
            pass
            def onFocus(self, focused):
            pass
            def onEnter(self):
            pass
            def refresh(self):
            pass


            To understand the code:



            • when initializing the first combo box I set its items to be all the feature classes in a workspace that I set. Since that workspace is a folder this results in a list of shapefiles that gets presented to me as a pulldown.

            • when initializing the second combo box I set its items to be an empty list and I also provide a hook (which seems to be an arbitrary property that could be named anything) to that list using ComboBoxClass2._hook=self

            • when I choose a shapefile from the first combo box its onSelChange function takes my selection and uses that to set the items in my hook to the second combo box to be the fields from the shapefile that I choose. Since ListFields returns a list of field objects I use list comprehension to turn that into a list of field names instead.

            enter image description here



            enter image description here






            share|improve this answer














            The code that I used to solve this was:



            import arcpy
            import pythonaddins

            class ComboBoxClass1(object):
            """Implementation for ComboBox_addin.combobox1 (ComboBox)"""
            def __init__(self):
            arcpy.env.workspace = r"C:polygeoQGIS"
            self.items = arcpy.ListFeatureClasses()
            self.editable = True
            self.enabled = True
            self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
            self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
            def onSelChange(self, selection):
            ComboBoxClass2._hook.items = [x.name for x in arcpy.ListFields(selection)]
            def onEditChange(self, text):
            pass
            def onFocus(self, focused):
            pass
            def onEnter(self):
            pass
            def refresh(self):
            pass

            class ComboBoxClass2(object):
            """Implementation for ComboBox_addin.combobox2 (ComboBox)"""
            def __init__(self):
            self.items =
            self.editable = True
            self.enabled = True
            self.dropdownWidth = 'WWWWWWWWWWWW'
            self.width = 'WWWWWWWWWWWW'
            ComboBoxClass2._hook=self
            def onSelChange(self, selection):
            pass
            def onEditChange(self, text):
            pass
            def onFocus(self, focused):
            pass
            def onEnter(self):
            pass
            def refresh(self):
            pass


            To understand the code:



            • when initializing the first combo box I set its items to be all the feature classes in a workspace that I set. Since that workspace is a folder this results in a list of shapefiles that gets presented to me as a pulldown.

            • when initializing the second combo box I set its items to be an empty list and I also provide a hook (which seems to be an arbitrary property that could be named anything) to that list using ComboBoxClass2._hook=self

            • when I choose a shapefile from the first combo box its onSelChange function takes my selection and uses that to set the items in my hook to the second combo box to be the fields from the shapefile that I choose. Since ListFields returns a list of field objects I use list comprehension to turn that into a list of field names instead.

            enter image description here



            enter image description here







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 11 mins ago









            Luke

            27.9k251101




            27.9k251101










            answered 5 hours ago









            PolyGeo♦

            52.3k1779236




            52.3k1779236











            • I'm currently doing something similar but using global variables instead of a Class._hook. I think I like the way you've done it better. But could you please explain the ._hook a bit further. Ie, is _hook just an arbitrarily named class property that you made up, or is it a built-in Python name?
              – Son of a Beach
              5 hours ago











            • @SonofaBeach I've not seen any documentation on it, the only source for it being available came from the earlier Q&A that I linked to in the question. I'm not enough of a Pythonista to be sure but I think it must be a property that either ArcPy or Python provides.
              – PolyGeo♦
              5 hours ago










            • What happens if you replace ._hook with something arbitrary like, .sharedInstance? (If you have a chance to try it out.) I can't find any documentation on _hook, and the only examples I can find for it make it look like it's just an arbitrary property.
              – Son of a Beach
              4 hours ago











            • @SonofaBeach You're right. I replaced ._hook with .sharedInstance and it worked just the same.
              – PolyGeo♦
              4 hours ago











            • Hey, thanks for trying this out. Looks like it's just a simple class attribute, which makes sense. I might go and update my own Add-In now to use a similar strategy instead of the global variables I'm currently using.
              – Son of a Beach
              4 hours ago
















            • I'm currently doing something similar but using global variables instead of a Class._hook. I think I like the way you've done it better. But could you please explain the ._hook a bit further. Ie, is _hook just an arbitrarily named class property that you made up, or is it a built-in Python name?
              – Son of a Beach
              5 hours ago











            • @SonofaBeach I've not seen any documentation on it, the only source for it being available came from the earlier Q&A that I linked to in the question. I'm not enough of a Pythonista to be sure but I think it must be a property that either ArcPy or Python provides.
              – PolyGeo♦
              5 hours ago










            • What happens if you replace ._hook with something arbitrary like, .sharedInstance? (If you have a chance to try it out.) I can't find any documentation on _hook, and the only examples I can find for it make it look like it's just an arbitrary property.
              – Son of a Beach
              4 hours ago











            • @SonofaBeach You're right. I replaced ._hook with .sharedInstance and it worked just the same.
              – PolyGeo♦
              4 hours ago











            • Hey, thanks for trying this out. Looks like it's just a simple class attribute, which makes sense. I might go and update my own Add-In now to use a similar strategy instead of the global variables I'm currently using.
              – Son of a Beach
              4 hours ago















            I'm currently doing something similar but using global variables instead of a Class._hook. I think I like the way you've done it better. But could you please explain the ._hook a bit further. Ie, is _hook just an arbitrarily named class property that you made up, or is it a built-in Python name?
            – Son of a Beach
            5 hours ago





            I'm currently doing something similar but using global variables instead of a Class._hook. I think I like the way you've done it better. But could you please explain the ._hook a bit further. Ie, is _hook just an arbitrarily named class property that you made up, or is it a built-in Python name?
            – Son of a Beach
            5 hours ago













            @SonofaBeach I've not seen any documentation on it, the only source for it being available came from the earlier Q&A that I linked to in the question. I'm not enough of a Pythonista to be sure but I think it must be a property that either ArcPy or Python provides.
            – PolyGeo♦
            5 hours ago




            @SonofaBeach I've not seen any documentation on it, the only source for it being available came from the earlier Q&A that I linked to in the question. I'm not enough of a Pythonista to be sure but I think it must be a property that either ArcPy or Python provides.
            – PolyGeo♦
            5 hours ago












            What happens if you replace ._hook with something arbitrary like, .sharedInstance? (If you have a chance to try it out.) I can't find any documentation on _hook, and the only examples I can find for it make it look like it's just an arbitrary property.
            – Son of a Beach
            4 hours ago





            What happens if you replace ._hook with something arbitrary like, .sharedInstance? (If you have a chance to try it out.) I can't find any documentation on _hook, and the only examples I can find for it make it look like it's just an arbitrary property.
            – Son of a Beach
            4 hours ago













            @SonofaBeach You're right. I replaced ._hook with .sharedInstance and it worked just the same.
            – PolyGeo♦
            4 hours ago





            @SonofaBeach You're right. I replaced ._hook with .sharedInstance and it worked just the same.
            – PolyGeo♦
            4 hours ago













            Hey, thanks for trying this out. Looks like it's just a simple class attribute, which makes sense. I might go and update my own Add-In now to use a similar strategy instead of the global variables I'm currently using.
            – Son of a Beach
            4 hours ago




            Hey, thanks for trying this out. Looks like it's just a simple class attribute, which makes sense. I might go and update my own Add-In now to use a similar strategy instead of the global variables I'm currently using.
            – Son of a Beach
            4 hours ago












            up vote
            0
            down vote













            I think setting a hook to a class instance to be accessed through a class property (as opposed to a property of an instance of that class) is bad practice and while it works fine here will cause you grief if you use this construct in other code. E.g. you write a class and create more than one instance of it or you have a superclass with this hook and you create multiple subclasses or multiple instances of a subclass. The hook property of the class will get overwritten each time an instance is created.



            What I do is use the instances of the classes, not the classes themselves.



            For example, in config.xml you will have something like:



            <?xml version="1.0"?>
            <ESRI.Configuration etc...>
            <etc...>
            <AddIn language="PYTHON" library="ComboBox_addin.py" namespace="ComboBox_addin">
            <ArcMap>
            <Commands>
            <ComboBox caption="CB1" category="Blah" class="ComboBoxClass1" id="ComboBox_addin.combobox1" etc...>etc...</ComboBox>
            <ComboBox caption="CB2" category="Blah" class="ComboBoxClass2" id="ComboBox_addin.combobox2" etc...>etc...</ComboBox>
            </Commands>
            <Extensions></Extensions>
            <Toolbars>
            <Toolbar caption="Blah blah" category="Blah" id="ComboBox_addin.toolbar" showInitially="true">
            <Items>
            <ComboBox refID="ComboBox_addin.combobox1"/>
            <ComboBox refID="ComboBox_addin.combobox2"/>
            </Items>
            </Toolbar>
            </Toolbars>
            <Menus></Menus>
            </ArcMap>
            </AddIn>
            </ESRI.Configuration>


            Note the id and refID are the same. These will refer to instances of these classes.



            Then you just replace references to ComboBoxClass2 to combobox2 in your code:



            import arcpy
            import pythonaddins

            class ComboBoxClass1(object):
            """Implementation for ComboBox_addin.combobox1 (ComboBox)"""
            def __init__(self):
            arcpy.env.workspace = r"C:polygeoQGIS"
            self.items = arcpy.ListFeatureClasses()
            self.editable = True
            self.enabled = True
            self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
            self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
            def onSelChange(self, selection):
            combobox2.items = [x.name for x in arcpy.ListFields(selection)] # <================
            def onEditChange(self, text):
            pass
            def onFocus(self, focused):
            pass
            def onEnter(self):
            pass
            def refresh(self):
            pass

            class ComboBoxClass2(object):
            """Implementation for ComboBox_addin.combobox2 (ComboBox)"""
            def __init__(self):
            self.items =
            self.editable = True
            self.enabled = True
            self.dropdownWidth = 'WWWWWWWWWWWW'
            self.width = 'WWWWWWWWWWWW'

            def onSelChange(self, selection):
            pass
            def onEditChange(self, text):
            pass
            def onFocus(self, focused):
            pass
            def onEnter(self):
            pass
            def refresh(self):
            pass


            If you run into a NameError (an issue with earlier ArcGIS versions, not sure if still a problem), put the following at the bottom of ComboBox_addin.py:
            :



            ##Workaround for 'NameError: global name 'combobox2' is not defined' - https://geonet.esri.com/thread/76833
            combobox1 = ComboBoxClass1()
            combobox2 = ComboBoxClass2()





            share|improve this answer


























              up vote
              0
              down vote













              I think setting a hook to a class instance to be accessed through a class property (as opposed to a property of an instance of that class) is bad practice and while it works fine here will cause you grief if you use this construct in other code. E.g. you write a class and create more than one instance of it or you have a superclass with this hook and you create multiple subclasses or multiple instances of a subclass. The hook property of the class will get overwritten each time an instance is created.



              What I do is use the instances of the classes, not the classes themselves.



              For example, in config.xml you will have something like:



              <?xml version="1.0"?>
              <ESRI.Configuration etc...>
              <etc...>
              <AddIn language="PYTHON" library="ComboBox_addin.py" namespace="ComboBox_addin">
              <ArcMap>
              <Commands>
              <ComboBox caption="CB1" category="Blah" class="ComboBoxClass1" id="ComboBox_addin.combobox1" etc...>etc...</ComboBox>
              <ComboBox caption="CB2" category="Blah" class="ComboBoxClass2" id="ComboBox_addin.combobox2" etc...>etc...</ComboBox>
              </Commands>
              <Extensions></Extensions>
              <Toolbars>
              <Toolbar caption="Blah blah" category="Blah" id="ComboBox_addin.toolbar" showInitially="true">
              <Items>
              <ComboBox refID="ComboBox_addin.combobox1"/>
              <ComboBox refID="ComboBox_addin.combobox2"/>
              </Items>
              </Toolbar>
              </Toolbars>
              <Menus></Menus>
              </ArcMap>
              </AddIn>
              </ESRI.Configuration>


              Note the id and refID are the same. These will refer to instances of these classes.



              Then you just replace references to ComboBoxClass2 to combobox2 in your code:



              import arcpy
              import pythonaddins

              class ComboBoxClass1(object):
              """Implementation for ComboBox_addin.combobox1 (ComboBox)"""
              def __init__(self):
              arcpy.env.workspace = r"C:polygeoQGIS"
              self.items = arcpy.ListFeatureClasses()
              self.editable = True
              self.enabled = True
              self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
              self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
              def onSelChange(self, selection):
              combobox2.items = [x.name for x in arcpy.ListFields(selection)] # <================
              def onEditChange(self, text):
              pass
              def onFocus(self, focused):
              pass
              def onEnter(self):
              pass
              def refresh(self):
              pass

              class ComboBoxClass2(object):
              """Implementation for ComboBox_addin.combobox2 (ComboBox)"""
              def __init__(self):
              self.items =
              self.editable = True
              self.enabled = True
              self.dropdownWidth = 'WWWWWWWWWWWW'
              self.width = 'WWWWWWWWWWWW'

              def onSelChange(self, selection):
              pass
              def onEditChange(self, text):
              pass
              def onFocus(self, focused):
              pass
              def onEnter(self):
              pass
              def refresh(self):
              pass


              If you run into a NameError (an issue with earlier ArcGIS versions, not sure if still a problem), put the following at the bottom of ComboBox_addin.py:
              :



              ##Workaround for 'NameError: global name 'combobox2' is not defined' - https://geonet.esri.com/thread/76833
              combobox1 = ComboBoxClass1()
              combobox2 = ComboBoxClass2()





              share|improve this answer
























                up vote
                0
                down vote










                up vote
                0
                down vote









                I think setting a hook to a class instance to be accessed through a class property (as opposed to a property of an instance of that class) is bad practice and while it works fine here will cause you grief if you use this construct in other code. E.g. you write a class and create more than one instance of it or you have a superclass with this hook and you create multiple subclasses or multiple instances of a subclass. The hook property of the class will get overwritten each time an instance is created.



                What I do is use the instances of the classes, not the classes themselves.



                For example, in config.xml you will have something like:



                <?xml version="1.0"?>
                <ESRI.Configuration etc...>
                <etc...>
                <AddIn language="PYTHON" library="ComboBox_addin.py" namespace="ComboBox_addin">
                <ArcMap>
                <Commands>
                <ComboBox caption="CB1" category="Blah" class="ComboBoxClass1" id="ComboBox_addin.combobox1" etc...>etc...</ComboBox>
                <ComboBox caption="CB2" category="Blah" class="ComboBoxClass2" id="ComboBox_addin.combobox2" etc...>etc...</ComboBox>
                </Commands>
                <Extensions></Extensions>
                <Toolbars>
                <Toolbar caption="Blah blah" category="Blah" id="ComboBox_addin.toolbar" showInitially="true">
                <Items>
                <ComboBox refID="ComboBox_addin.combobox1"/>
                <ComboBox refID="ComboBox_addin.combobox2"/>
                </Items>
                </Toolbar>
                </Toolbars>
                <Menus></Menus>
                </ArcMap>
                </AddIn>
                </ESRI.Configuration>


                Note the id and refID are the same. These will refer to instances of these classes.



                Then you just replace references to ComboBoxClass2 to combobox2 in your code:



                import arcpy
                import pythonaddins

                class ComboBoxClass1(object):
                """Implementation for ComboBox_addin.combobox1 (ComboBox)"""
                def __init__(self):
                arcpy.env.workspace = r"C:polygeoQGIS"
                self.items = arcpy.ListFeatureClasses()
                self.editable = True
                self.enabled = True
                self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
                self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
                def onSelChange(self, selection):
                combobox2.items = [x.name for x in arcpy.ListFields(selection)] # <================
                def onEditChange(self, text):
                pass
                def onFocus(self, focused):
                pass
                def onEnter(self):
                pass
                def refresh(self):
                pass

                class ComboBoxClass2(object):
                """Implementation for ComboBox_addin.combobox2 (ComboBox)"""
                def __init__(self):
                self.items =
                self.editable = True
                self.enabled = True
                self.dropdownWidth = 'WWWWWWWWWWWW'
                self.width = 'WWWWWWWWWWWW'

                def onSelChange(self, selection):
                pass
                def onEditChange(self, text):
                pass
                def onFocus(self, focused):
                pass
                def onEnter(self):
                pass
                def refresh(self):
                pass


                If you run into a NameError (an issue with earlier ArcGIS versions, not sure if still a problem), put the following at the bottom of ComboBox_addin.py:
                :



                ##Workaround for 'NameError: global name 'combobox2' is not defined' - https://geonet.esri.com/thread/76833
                combobox1 = ComboBoxClass1()
                combobox2 = ComboBoxClass2()





                share|improve this answer














                I think setting a hook to a class instance to be accessed through a class property (as opposed to a property of an instance of that class) is bad practice and while it works fine here will cause you grief if you use this construct in other code. E.g. you write a class and create more than one instance of it or you have a superclass with this hook and you create multiple subclasses or multiple instances of a subclass. The hook property of the class will get overwritten each time an instance is created.



                What I do is use the instances of the classes, not the classes themselves.



                For example, in config.xml you will have something like:



                <?xml version="1.0"?>
                <ESRI.Configuration etc...>
                <etc...>
                <AddIn language="PYTHON" library="ComboBox_addin.py" namespace="ComboBox_addin">
                <ArcMap>
                <Commands>
                <ComboBox caption="CB1" category="Blah" class="ComboBoxClass1" id="ComboBox_addin.combobox1" etc...>etc...</ComboBox>
                <ComboBox caption="CB2" category="Blah" class="ComboBoxClass2" id="ComboBox_addin.combobox2" etc...>etc...</ComboBox>
                </Commands>
                <Extensions></Extensions>
                <Toolbars>
                <Toolbar caption="Blah blah" category="Blah" id="ComboBox_addin.toolbar" showInitially="true">
                <Items>
                <ComboBox refID="ComboBox_addin.combobox1"/>
                <ComboBox refID="ComboBox_addin.combobox2"/>
                </Items>
                </Toolbar>
                </Toolbars>
                <Menus></Menus>
                </ArcMap>
                </AddIn>
                </ESRI.Configuration>


                Note the id and refID are the same. These will refer to instances of these classes.



                Then you just replace references to ComboBoxClass2 to combobox2 in your code:



                import arcpy
                import pythonaddins

                class ComboBoxClass1(object):
                """Implementation for ComboBox_addin.combobox1 (ComboBox)"""
                def __init__(self):
                arcpy.env.workspace = r"C:polygeoQGIS"
                self.items = arcpy.ListFeatureClasses()
                self.editable = True
                self.enabled = True
                self.dropdownWidth = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
                self.width = 'WWWWWWWWWWWWWWWWWWWWWWWWWWWW'
                def onSelChange(self, selection):
                combobox2.items = [x.name for x in arcpy.ListFields(selection)] # <================
                def onEditChange(self, text):
                pass
                def onFocus(self, focused):
                pass
                def onEnter(self):
                pass
                def refresh(self):
                pass

                class ComboBoxClass2(object):
                """Implementation for ComboBox_addin.combobox2 (ComboBox)"""
                def __init__(self):
                self.items =
                self.editable = True
                self.enabled = True
                self.dropdownWidth = 'WWWWWWWWWWWW'
                self.width = 'WWWWWWWWWWWW'

                def onSelChange(self, selection):
                pass
                def onEditChange(self, text):
                pass
                def onFocus(self, focused):
                pass
                def onEnter(self):
                pass
                def refresh(self):
                pass


                If you run into a NameError (an issue with earlier ArcGIS versions, not sure if still a problem), put the following at the bottom of ComboBox_addin.py:
                :



                ##Workaround for 'NameError: global name 'combobox2' is not defined' - https://geonet.esri.com/thread/76833
                combobox1 = ComboBoxClass1()
                combobox2 = ComboBoxClass2()






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 3 hours ago

























                answered 3 hours ago









                Luke

                27.9k251101




                27.9k251101



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fgis.stackexchange.com%2fquestions%2f300756%2fusing-two-python-addin-combo-boxes-to-choose-feature-class-first-then-field-from%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Comments

                    Popular posts from this blog

                    Long meetings (6-7 hours a day): Being “babysat” by supervisor

                    Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

                    Confectionery