How to handle an event for a combobox

Hello! Friends, I have two comboboxes. I would like the second drop-down list to change depending on the choice of value in the first. The selection of dropdown lists is in one function. How can we make the code understand that having selected a value in the first list, we need to select another or change the list of the second combobox? I was told that for this it is necessary to launch an event for the combobox, but how to implement this technically?

import clr
import sys
import System

clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")
import System.Drawing
import System.Windows.Forms
from System.Drawing import *
from System.Windows.Forms import *
clr.AddReference('RevitAPI')
import Autodesk.Revit.DB as DB
clr.AddReference("RevitAPIUI")
from  Autodesk.Revit.UI import *
clr.AddReference('DSCoreNodes')
import DSCore
from System.Collections.Generic import List
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
doc = DocumentManager.Instance.CurrentDBDocument
from collections import namedtuple

def CatElemTypes(name):
	cats = doc.Settings.Categories
	catsN = sorted([c.Name for c in cats])
	c1 = [i for i in cats if i.Name == name][0]
	bc1 = System.Enum.ToObject(DB.BuiltInCategory, c1.Id.IntegerValue)
	bc1el = DB.FilteredElementCollector(doc).OfCategory(bc1).WhereElementIsElementType().ToElements()
	return bc1el
def Cats(name):
	cats = doc.Settings.Categories
	catsN = sorted([c.Name for c in cats])
	c1 = [i for i in cats if i.Name == name][0]
	return c1

class MyItem():
	def __init__(self, key, value):
		self.Key = key
		self.Value = value
  
list_cats = ['Walls','Doors','Windows','Rooms','Floors','Ceilings','Structural Columns']
list_cats1 = [Cats(i).Name for i in list_cats]
list_cats2 = [1,2,3,4,5,6,7]
list_params = ['Type Name','Type Comments','Description','Type Mark','Width','Height','Sill Height','Base Offset','Unconnected Height','Top Offset','Default Thickness','Height Offset','Family Name','Limit Offset','Wall Finish']
list_params1 = [1,2,3,4,5,6,7,9,10,11,12,13,17,18,20]
if list_cats2==1:
	list_params1 = [1,2,3,4,5,9,10,11]
list_ravno = ['<','=','>']
list_ravno1 = [0,1,2]
list_of_items_cats = [MyItem(i,j) for i,j in zip(list_cats1,list_cats2)]
list_of_items_params = [MyItem(i,j) for i,j in zip(list_params,list_params1)]
list_of_items_ravno = [MyItem(i,j) for i,j in zip(list_ravno,list_ravno1)]
OUT = list_params
class MainForm(Form):
	def __init__(self):
		self.out = []
		self.choice = None
		self.InitializeComponent()
	
	def InitializeComponent(self):
		self.FormBorderStyle  = FormBorderStyle.FixedDialog ##Remove the maximize box.
		self.MaximizeBox = False            ## Set the MinimizeBox to false to remove the minimize box.
		self.MinimizeBox = False            ## Set the accept button of the form to button1.
		self.StartPosition = FormStartPosition.CenterScreen
		self.AutoScroll = False
		self.ScrollBars = ScrollBars.Vertical
		self.ClientSize = System.Drawing.Size(500, 235)
		self.Name = "Title"#"Вихідні дані"
		self.Text = "Title"#"Вихідні дані"
		self.ResumeLayout(True)
		#
		self._label1 = System.Windows.Forms.Label()
		self._label2 = System.Windows.Forms.Label()
		self._label3 = System.Windows.Forms.Label()
		self._label4 = System.Windows.Forms.Label()
		self._label5 = System.Windows.Forms.Label()
		self._checkBox1 = System.Windows.Forms.CheckBox()
		#
		self._label1.Location = System.Drawing.Point(20, 25)
		self._label1.Name = "label1"
		self._label1.Size = System.Drawing.Size(250, 23)
		self._label1.TabIndex = 1
		self._label1.Text = "Select Category"#"Виберіть категорію" 
		self._label1.Font = System.Drawing.Font("Tahoma", 16, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0) 
		#
		self._label2.Location = System.Drawing.Point(20, 60)
		self._label2.Name = "label2"
		self._label2.Size = System.Drawing.Size(250, 23)
		self._label2.TabIndex = 1
		self._label2.Text = "Select Parameter"#"Виберіть параметр" 
		self._label2.Font = System.Drawing.Font("Tahoma", 16, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0)  
		#
		self._label3.Location = System.Drawing.Point(20, 95)
		self._label3.Name = "label3"
		self._label3.Size = System.Drawing.Size(250, 23)
		self._label3.TabIndex = 1
		self._label3.Text = "Value"#"Введіть дані"
		self._label3.Font = System.Drawing.Font("Tahoma", 16, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0)   
		#
		self._label4.Location = System.Drawing.Point(20, 130)
		self._label4.Name = "label4"
		self._label4.Size = System.Drawing.Size(250, 23)
		self._label4.TabIndex = 1
		self._label4.Text = "Equals/Contains"#"Дорівнює/Включає" 
		self._label4.Font = System.Drawing.Font("Tahoma", 16, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0)  
		#
		self._label5.Location = System.Drawing.Point(20, 165)
		self._label5.Name = "label5"
		self._label5.Size = System.Drawing.Size(100, 23)
		self._label5.TabIndex = 1
		self._label5.Text = "<,=,>"  
		self._label5.Font = System.Drawing.Font("Tahoma", 16, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0) 
		#
		self._comboBoxType = System.Windows.Forms.ComboBox()
		self.Controls.Add(self._comboBoxType) # move to here
		self._comboBoxType.Location = System.Drawing.Point(280, 25)
		self._comboBoxType.Size = System.Drawing.Size(200, 20)
		self._comboBoxType.DataSource = list_of_items_cats
		self._comboBoxType.DisplayMember = "Key"
		self._comboBoxType.ValueMember = "Value"
		self._comboBoxType.SelectedIndex = 0 # added
		#self._comboBoxType.SelectedIndexChanged += self.ComboBox1SelectedIndexChanged
		self._comboBoxType.Font = System.Drawing.Font("Tahoma", 14, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0) 
		#
		self._cb = System.Windows.Forms.ComboBox()
		self.Controls.Add(self._cb) # move to here
		self._cb.Location = System.Drawing.Point(280, 60)
		self._cb.Size = System.Drawing.Size(200, 20)
		self._cb.DataSource = list_of_items_params
		self._cb.DisplayMember = "Key"
		self._cb.ValueMember = "Value"
		self._cb.SelectedIndex = 0 # added
		#self._cb.SelectedIndexChanged += self.ComboBox1SelectedIndexChanged
		self._cb.Font = System.Drawing.Font("Tahoma", 14, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0)
		#
		self._text_value = System.Windows.Forms.TextBox()
		self._text_value.Location = System.Drawing.Point(280, 95)
		self._text_value.Name = "Значення"
		self._text_value.Text = ""
		self._text_value.Size = System.Drawing.Size(200, 20)
		self._text_value.Font = System.Drawing.Font("Tahoma", 14, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0) 
		#
		self._checkBox1.Name = "checkBox1"
		self._checkBox1.Location = System.Drawing.Point(380, 130)
		self._checkBox1.Size = System.Drawing.Size(30, 30)
		self._checkBox1.TabIndex = 0
		self._checkBox1.UseVisualStyleBackColor = True
		#self._checkBoxSelectAll.CheckedChanged += self.CheckBoxSelectChecked
		#
		self._cb1 = System.Windows.Forms.ComboBox()
		self.Controls.Add(self._cb1) # move to here
		self._cb1.Location = System.Drawing.Point(380, 165)
		self._cb1.Size = System.Drawing.Size(100, 20)
		self._cb1.DataSource = list_of_items_ravno
		self._cb1.DisplayMember = "Key"
		self._cb1.ValueMember = "Value"
		self._cb1.SelectedIndex = 1 # added #вибирає який по порядку елемент з'являється
		#self._cb1.SelectedIndexChanged += self.ComboBox1SelectedIndexChanged
		self._cb1.Font = System.Drawing.Font("Tahoma", 14, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0) 
		#
		self.button = System.Windows.Forms.Button()
		self.button.Text = 'Next'
		self.button.Location = Point(170,180)
		self.button.Width = 150
		self.button.Height = 35
		self.button.Click += self.button_click
		self.button.Font = System.Drawing.Font("Tahoma", 14, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0) 
		#
		self.Controls.Add(self._label1)
		self.Controls.Add(self._label2)
		self.Controls.Add(self._label3)
		self.Controls.Add(self._label4)
		self.Controls.Add(self._label5)
		self.Controls.Add(self._text_value)
		self.Controls.Add(self._checkBox1)
		self.Controls.Add(self.button)

	#def ComboBox1SelectedIndexChanged(self, sender, e):
		#self.choice = sender.SelectedItem.Value

	def button_click(self, sender, event):
		self.out.append(self._comboBoxType.SelectedItem.Value)
		self.out.append(self._cb.SelectedItem.Value)
		self.out.append(self._text_value.Text)
		self.out.append(self._checkBox1.CheckState)
		self.out.append(self._cb1.SelectedItem.Value)
		self.Close()

objForm = MainForm()
objForm.ShowDialog()
result = [objForm.out[0],objForm.out[1],objForm.out[2],objForm.out[3].value__,objForm.out[4]]
OUT = result

Hi @TOXA240701 and welcome !

Subscribe event here

self._comboBoxType.SelectedIndexChanged += self.ComboBox1SelectedIndexChanged

and implement the DroppedDown property in the event-handling method

	def ComboBox1SelectedIndexChanged(self, sender, e):
		#print(sender.Name)
		self._cb.DroppedDown = True
1 Like

Thanks a lot for the advice, c.poupin. But I’m still far from properly understanding how Winform works. If it’s not difficult for you, please tell me approximately where what needs to be replaced. My goal is to have a list of other content drop out of the second combo box when the first one is selected. I tried to apply your hint using the DropDown method, but I still didn’t understand where to enter the condition that will change the second list?..
I have options in the list for all categories, but I want to separate them so that only those that belong to the wall category are displayed for walls, and only those that correspond to them are displayed for doors. Sorry, maybe I asked the wrong question initially. The picture shows approximately

Hi,

I might be mistaken, but I believe the drop-down list is loaded when the winform first fires.

I don’t think you can ‘rebuild’ the 2nd drop down by using values from the first in the same winform?

I tend to handle this by having a 2nd winform, which takes the value from the drop down in the 1st winform and uses that to build the 2nd drop down list…

I hope that helps,

Mark

1 Like

Thank you, Mark. I hoped that this could be done in one window for ease of review and selection. If this is not possible, I have no questions.

1 Like

you need to clear and replace the DataSource of the second combobox

an example with 2 data tables (filtering the second data table with the value selected in the first combobox)

test_combobox+DataTable

python code (with IronPython2/3 for this example)

import clr
import sys
import System

#import net library
from System import Array
from System.Collections.Generic import List, IList, Dictionary
clr.AddReference('System.Data')
from System.Data import *

clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")
import System.Drawing
import System.Windows.Forms

from System.Drawing import *
from System.Windows.Forms import *

clr.AddReference("System.Core")
import System.Linq
from System.Linq import *
clr.ImportExtensions(System.Linq)
clr.AddReference('System.Data.DataSetExtensions')
clr.ImportExtensions(System.Data.DataTableExtensions)


class MyClass:
    def __init__(self, value):
        self.value = value
    def __repr__(self):
        return "object {}".format(self.value)

class MainForm(Form):
    def __init__(self):
        # array_data1 = [[A, 65], [B, 66], [C, 67]...]
        array_data1 = [[chr(i), MyClass(chr(i))] for i in range(65, 69)]
        # array_data1 = [[A, 65, A65], [A, 66, A66], [A, 67, A67]...]
        array_data2 = [[chr(i)+ str(j), chr(i), MyClass(chr(i)+ str(j))] for i in range(65, 69) for j in range(10)]
        print(array_data2)
        # create Table1 
        self._tableA = DataTable("TableA")
        self._tableA.Rows.Add() # to add a empty row
        self._tableA.AcceptChanges() # to add a empty row
        self._tableA.Columns.Add("Key", System.String)
        self._tableA.Columns.Add("Value", object)
        # populate dataTable
        [self._tableA.Rows.Add(i, j) for i, j in array_data1]
        # create Table2 
        self._tableB = DataTable("TableB")
        self._tableB.Rows.Add() # to add a empty row
        self._tableB.AcceptChanges() # to add a empty row
        self._tableB.Columns.Add("Key", System.String)
        self._tableB.Columns.Add("ParentKey", System.String)
        self._tableB.Columns.Add("Value", object)
        # populate dataTable
        [self._tableB.Rows.Add(i, j, k) for i, j, k in array_data2]
        self.choiceA = None
        self.choiceB = None
        self.InitializeComponent()
    
    def InitializeComponent(self):
    
        self._comboBoxType = System.Windows.Forms.ComboBox()
        self._comboBoxInstance = System.Windows.Forms.ComboBox()
        #
        self._comboBoxType.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right
        self._comboBoxType.Location = System.Drawing.Point(40, 50)
        self._comboBoxType.Size = System.Drawing.Size(221, 21)
        self._comboBoxType.Text = "Choice..."
        self._comboBoxType.DataSource = self._tableA.Copy()
        self._comboBoxType.DisplayMember = "Key"
        self._comboBoxType.ValueMember = "Value"
        self._comboBoxType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
        self._comboBoxType.SelectedIndexChanged += self.ComboBoxTypeSelectedIndexChanged
        #
        self._comboBoxInstance.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right
        self._comboBoxInstance.Location = System.Drawing.Point(40, 100)
        self._comboBoxInstance.Size = System.Drawing.Size(221, 21)
        self._comboBoxInstance.Text = "Choice..."
        self._comboBoxInstance.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
        self._comboBoxInstance.SelectionChangeCommitted += self.ComboBoxInstanceSelectedCommitted
    
        self.ClientSize = System.Drawing.Size(300, 250)
        self.MinimumSize = self.ClientSize + System.Drawing.Size(20, 30)
        self.Controls.Add(self._comboBoxType)
        self.Controls.Add(self._comboBoxInstance)
        self.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show
        self.Name = "MainForm"
        self.Text = "MainForm"
        self.ResumeLayout(False)
        
    def ComboBoxTypeSelectedIndexChanged(self, sender, e):
        print(sender.SelectedItem) # get dataRow
        print(sender.SelectedItem['Key'])  # get Name of dataRow
        print(sender.SelectedItem['Value'])  # get value of dataRow
        if isinstance(sender.SelectedItem['Value'], System.DBNull):
            self.choiceA = None
        else:
            self.choiceA = sender.SelectedItem['Value']
        print(self.choiceA)
        # clear DataSource
        self._comboBoxInstance.DataSource = None
        # filer the tableB from choiceA value
        strDataExpression = "[ParentKey] = '{}'".format(sender.SelectedItem['Key'])
        dt_B = self._tableB.Select(strDataExpression).CopyToDataTable()
        self._comboBoxInstance.DataSource = dt_B
        self._comboBoxInstance.DisplayMember = "Key"
        self._comboBoxInstance.ValueMember = "Value"
        self._comboBoxInstance.DroppedDown = True
            
    def ComboBoxInstanceSelectedCommitted(self, sender, e):
        if isinstance(sender.SelectedItem['Value'], System.DBNull):
            self.choiceB = None
        else:
            self.choiceB = sender.SelectedItem['Value']
            
            
objForm = MainForm()
objForm.ShowDialog()
        
OUT = [objForm.choiceA, objForm.choiceA.value], [objForm.choiceB, objForm.choiceB.value]
3 Likes

Very cool! I see that it works and there is an option. I just can’t insert the data correctly(. If I change the belonging of the first combobox to my list, it gives one error, if I leave it as it was and change the second, then another error pops up with the same logs. It’s difficult to track what’s happening in the function def init(self ) and how do I substitute my lists if the functions cannot be checked with the standard dir() method. I’ll try to do something else, but I don’t know how to approach the code. This is a great task, but I’m still very far from its level. . Many thanks for your help!

I managed to replace the old lists with my own, and the name of the selected category appeared in the second combo box (I deleted it). But it turns out that I have a slightly different task - my lists from the second combo box will be of different lengths and will depend on the category. If I understand correctly, we define the second list in the first class function def init(self) and define the selected category later in the third function def ComboBoxTypeSelectedIndexChanged(self, sender, e)… So far the solution eludes me

> import clr
> import sys
> import System
> 
> #import net library
> from System import Array
> from System.Collections.Generic import List, IList, Dictionary
> clr.AddReference('System.Data')
> from System.Data import *
> 
> clr.AddReference("System.Drawing")
> clr.AddReference("System.Windows.Forms")
> import System.Drawing
> import System.Windows.Forms
> 
> from System.Drawing import *
> from System.Windows.Forms import *
> 
> clr.AddReference("System.Core")
> import System.Linq
> from System.Linq import *
> clr.ImportExtensions(System.Linq)
> clr.AddReference('System.Data.DataSetExtensions')
> clr.ImportExtensions(System.Data.DataTableExtensions)
> 
> clr.AddReference('RevitAPI')
> import Autodesk.Revit.DB as DB
> clr.AddReference("RevitAPIUI")
> from  Autodesk.Revit.UI import *
> clr.AddReference('DSCoreNodes')
> import DSCore
> from System.Collections.Generic import List
> clr.AddReference('RevitServices')
> import RevitServices
> from RevitServices.Persistence import DocumentManager
> from RevitServices.Transactions import TransactionManager
> uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
> doc = DocumentManager.Instance.CurrentDBDocument
> from collections import namedtuple
> 
> def CatElemTypes(name):
> 	cats = doc.Settings.Categories
> 	catsN = sorted([c.Name for c in cats])
> 	c1 = [i for i in cats if i.Name == name][0]
> 	bc1 = System.Enum.ToObject(DB.BuiltInCategory, c1.Id.IntegerValue)
> 	bc1el = DB.FilteredElementCollector(doc).OfCategory(bc1).WhereElementIsElementType().ToElements()
> 	return bc1el
> def Cats(name):
> 	cats = doc.Settings.Categories
> 	catsN = sorted([c.Name for c in cats])
> 	c1 = [i for i in cats if i.Name == name][0]
> 	return c1
> 
> class MyItem():
> 	def __init__(self, key, value):
> 		self.Key = key
> 		self.Value = value
> 
> list_cats = ['Walls','Doors','Windows','Rooms','Floors','Ceilings','Structural Columns']
> list_cats1 = [Cats(i).Name for i in list_cats]
> list_cats2 = [1,2,3,4,5,6,7]
> list_params = ['Type Name','Type Comments','Description','Type Mark','Width','Height','Sill Height','Base Offset','Unconnected Height','Top Offset','Default Thickness','Height Offset','Family Name','Limit Offset','Wall Finish']
> list_params1 = [1,2,3,4,5,6,7,9,10,11,12,13,17,18,20]
> list_params10 = ['Type Name','Type Comments','Description','Type Mark','Width','Base Offset','Unconnected Height','Top Offset']
> list_params11 = [1,2,3,4,5,9,10,11]
> list_ravno = ['<','=','>']
> list_ravno1 = [0,1,2]
> list_of_items_cats = [MyItem(i,j) for i,j in zip(list_cats1,list_cats2)]
> list_of_items_params = [MyItem(i,j) for i,j in zip(list_params,list_params1)]
> list_of_items_params1 = [MyItem(i,j) for i,j in zip(list_params10,list_params11)]
> list_of_items_ravno = [MyItem(i,j) for i,j in zip(list_ravno,list_ravno1)]
> 
> list1_of_items_cats = [[i,j] for i,j in zip(list_cats1,list_cats2)]
> list1_of_items_params = [[i,j] for i,j in zip(list_params,list_params1)]
> 
> class MyClass:
>     def __init__(self, value):
>         self.value = value
>     def __repr__(self):
>     	return self.value
> 
> class MainForm(Form):
>     def __init__(self):
>         # array_data1 = [[A, 65], [B, 66], [C, 67]...]
>         array_data1 = [[i, MyClass(i)] for i in list_cats]
>         # array_data1 = [[A, 65, A65], [A, 66, A66], [A, 67, A67]...]
>         array_data2 = [[str(j), i, MyClass(str(j))] for i in list_cats for j in list_params]
>         print(array_data2)
>         # create Table1 
>         self._tableA = DataTable("TableA")
>         self._tableA.Rows.Add() # to add a empty row
>         self._tableA.AcceptChanges() # to add a empty row
>         self._tableA.Columns.Add("Key", System.String)
>         self._tableA.Columns.Add("Value", object)
>         # populate dataTable
>         [self._tableA.Rows.Add(i, j) for i, j in array_data1]
>         # create Table2 
>         self._tableB = DataTable("TableB")
>         self._tableB.Rows.Add() # to add a empty row
>         self._tableB.AcceptChanges() # to add a empty row
>         self._tableB.Columns.Add("Key", System.String)
>         self._tableB.Columns.Add("ParentKey", System.String)
>         self._tableB.Columns.Add("Value", object)
>         # populate dataTable
>         [self._tableB.Rows.Add(i, j, k) for i, j, k in array_data2]
>         self.choiceA = None
>         self.choiceB = None
>         self.InitializeComponent()
>     
>     def InitializeComponent(self):
>     
>         self._comboBoxType = System.Windows.Forms.ComboBox()
>         self._comboBoxInstance = System.Windows.Forms.ComboBox()
>         #
>         self._comboBoxType.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right
>         self._comboBoxType.Location = System.Drawing.Point(40, 50)
>         self._comboBoxType.Size = System.Drawing.Size(221, 21)
>         self._comboBoxType.Text = "Choice..."
>         self._comboBoxType.DataSource = self._tableA.Copy()
>         self._comboBoxType.DisplayMember = "Key"
>         self._comboBoxType.ValueMember = "Value"
>         self._comboBoxType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
>         self._comboBoxType.SelectedIndexChanged += self.ComboBoxTypeSelectedIndexChanged
>         #
>         self._comboBoxInstance.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right
>         self._comboBoxInstance.Location = System.Drawing.Point(40, 100)
>         self._comboBoxInstance.Size = System.Drawing.Size(221, 21)
>         self._comboBoxInstance.Text = "Choice..."
>         self._comboBoxInstance.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
>         self._comboBoxInstance.SelectionChangeCommitted += self.ComboBoxInstanceSelectedCommitted
>     
>         self.ClientSize = System.Drawing.Size(300, 250)
>         self.MinimumSize = self.ClientSize + System.Drawing.Size(20, 30)
>         self.Controls.Add(self._comboBoxType)
>         self.Controls.Add(self._comboBoxInstance)
>         self.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show
>         self.Name = "MainForm"
>         self.Text = "MainForm"
>         self.ResumeLayout(False)
>         
>     def ComboBoxTypeSelectedIndexChanged(self, sender, e):
>         #print(sender.SelectedItem) # get dataRow
>         #print(sender.SelectedItem['Key'])  # get Name of dataRow
>         #print(sender.SelectedItem['Value'])  # get value of dataRow
>         if isinstance(sender.SelectedItem['Value'], System.DBNull):
>             self.choiceA = None
>         else:
>             self.choiceA = sender.SelectedItem['Value']
>         #print(self.choiceA)
>         # clear DataSource
>         self._comboBoxInstance.DataSource = None
>         # filer the tableB from choiceA value
>         strDataExpression = "[ParentKey] = '{}'".format(sender.SelectedItem['Key'])
>         dt_B = self._tableB.Select(strDataExpression).CopyToDataTable()
>         self._comboBoxInstance.DataSource = dt_B
>         self._comboBoxInstance.DisplayMember = "Key"
>         self._comboBoxInstance.ValueMember = "Value"
>         self._comboBoxInstance.DroppedDown = True
>             
>     def ComboBoxInstanceSelectedCommitted(self, sender, e):
>         if isinstance(sender.SelectedItem['Value'], System.DBNull):
>             self.choiceB = None
>         else:
>             self.choiceB = sender.SelectedItem['Value']
>                      
> objForm = MainForm()
> objForm.ShowDialog()
>     
> OUT = [objForm.choiceA, objForm.choiceA], [objForm.choiceB, objForm.choiceB]

Image 10

Hi,
alternatively, you can use a dictionary as input

import clr
import sys
import System

#import net library
from System import Array
from System.Collections.Generic import List, IList, Dictionary
clr.AddReference('System.Data')
from System.Data import *

clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")
import System.Drawing
import System.Windows.Forms

from System.Drawing import *
from System.Windows.Forms import *

clr.AddReference("System.Core")
import System.Linq
from System.Linq import *
clr.ImportExtensions(System.Linq)
clr.AddReference('System.Data.DataSetExtensions')
clr.ImportExtensions(System.Data.DataTableExtensions)


class MyClass:
    def __init__(self, value):
        self.value = value
    def __repr__(self):
        return "object {}".format(self.value)

class MainForm(Form):
    def __init__(self, my_dict):
        self._my_dict = my_dict
        self.choiceA = None
        self.choiceB = None
        self.InitializeComponent()
    
    def InitializeComponent(self):
    
        self._comboBoxType = System.Windows.Forms.ComboBox()
        self._comboBoxInstance = System.Windows.Forms.ComboBox()
        #
        self._comboBoxType.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right
        self._comboBoxType.Location = System.Drawing.Point(40, 50)
        self._comboBoxType.Size = System.Drawing.Size(221, 21)
        self._comboBoxType.Text = "Choice..."
        self._comboBoxType.Items.AddRange(System.Array[System.Object](sorted(self._my_dict.keys())))
        self._comboBoxType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
        self._comboBoxType.SelectedIndexChanged += self.ComboBoxTypeSelectedIndexChanged
        #
        self._comboBoxInstance.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right
        self._comboBoxInstance.Location = System.Drawing.Point(40, 100)
        self._comboBoxInstance.Size = System.Drawing.Size(221, 21)
        self._comboBoxInstance.Text = "Choice..."
        self._comboBoxInstance.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
        self._comboBoxInstance.SelectionChangeCommitted += self.ComboBoxInstanceSelectedCommitted
    
        self.ClientSize = System.Drawing.Size(300, 250)
        self.MinimumSize = self.ClientSize + System.Drawing.Size(20, 30)
        self.Controls.Add(self._comboBoxType)
        self.Controls.Add(self._comboBoxInstance)
        self.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show
        self.Name = "MainForm"
        self.Text = "MainForm"
        self.ResumeLayout(False)
        
    def ComboBoxTypeSelectedIndexChanged(self, sender, e):
        self.choiceA = sender.SelectedItem
        # clear Items
        self._comboBoxInstance.Items.Clear()
        values = self._my_dict.get(self.choiceA)
        self._comboBoxInstance.Items.AddRange(System.Array[System.Object](values))
        self._comboBoxInstance.DroppedDown = True
            
    def ComboBoxInstanceSelectedCommitted(self, sender, e):
        self.choiceB = sender.SelectedItem
            
my_dict = IN[0]
objForm = MainForm(my_dict)
objForm.ShowDialog()
        
OUT = objForm.choiceA, objForm.choiceB
4 Likes

Cyril, thank you very much! You helped me a lot. I entered my values, tinkered with the code a little and changed a few things, and I already have the desired one-window view!!! God bless you!

import clr
import sys
import System

clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")
import System.Drawing
import System.Windows.Forms
from System.Drawing import *
from System.Windows.Forms import *
clr.AddReference('RevitAPI')
import Autodesk.Revit.DB as DB
clr.AddReference("RevitAPIUI")
from  Autodesk.Revit.UI import *
clr.AddReference('DSCoreNodes')
import DSCore
from System.Collections.Generic import List
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
doc = DocumentManager.Instance.CurrentDBDocument
from collections import namedtuple

def CatElemTypes(name):
	cats = doc.Settings.Categories
	catsN = sorted([c.Name for c in cats])
	c1 = [i for i in cats if i.Name == name][0]
	bc1 = System.Enum.ToObject(DB.BuiltInCategory, c1.Id.IntegerValue)
	bc1el = DB.FilteredElementCollector(doc).OfCategory(bc1).WhereElementIsElementType().ToElements()
	return bc1el
def Cats(name):
	cats = doc.Settings.Categories
	catsN = sorted([c.Name for c in cats])
	c1 = [i for i in cats if i.Name == name][0]
	return c1

class MyItem():
	def __init__(self, key, value):
		self.Key = key
		self.Value = value
  
list_cats = ['Walls','Doors','Windows','Rooms','Floors','Ceilings','Structural Columns']
list_cats1 = [Cats(i).Name for i in list_cats]
list_cats2 = [1,2,3,4,5,6,7]
list_of_items_cats = [MyItem(i,j) for i,j in zip(list_cats1,list_cats2)]
list_params = ['Type Name','Type Comments','Description','Type Mark','Width','Height','Sill Height','Base Offset','Unconnected Height','Top Offset','Default Thickness','Height Offset From Level',"Classification.Uniclass.Ss.Number",'Family Name','Limit Offset','Wall Finish']
list_params1 = [1,2,3,4,5,6,7,9,10,11,12,13,16,17,18,20]
list_params10 = ['Type Name','Type Comments','Description','Type Mark','Width','Base Offset','Unconnected Height','Top Offset']
list_params20 = ['Type Name','Type Comments','Description','Type Mark','Width','Height','Sill Height',"Classification.Uniclass.Ss.Number",'Family Name']
list_params30 = ['Type Name','Type Comments','Description','Type Mark','Width','Height','Base Offset',"Classification.Uniclass.Ss.Number",'Family Name']
list_params40 = ['Base Offset','Limit Offset','Wall Finish']
list_params50 = ['Type Name','Type Comments','Description','Type Mark','Default Thickness','Height Offset From Level',"Classification.Uniclass.Ss.Number"]
list_params60 = ['Type Name','Type Comments','Description','Type Mark','Height Offset From Level']
list_params70 = ['Type Name','Type Comments','Description','Type Mark','Base Offset','Top Offset',"Classification.Uniclass.Ss.Number"]
list_cats_all = {k:[k+i for i in v] for k,v in zip(list_cats, [list_params10,list_params20,list_params30,list_params40,list_params50,list_params60,list_params70])}
list_ravno = ['<','=','>']
list_ravno1 = [0,1,2]
list_of_items_ravno = [MyItem(i,j) for i,j in zip(list_ravno,list_ravno1)]

class MyClass:
	def __init__(self, value):
		self.value = value
	def __repr__(self):
		return "object {}".format(self.value)

class MainForm(Form):
	def __init__(self, my_dict):
		self._my_dict = my_dict
		self.choiceA = None
		self.choiceB = None
		self.out = []
		self.InitializeComponent()
	
	def InitializeComponent(self):
		self.FormBorderStyle  = FormBorderStyle.FixedDialog ##Remove the maximize box.
		self.MaximizeBox = False            ## Set the MinimizeBox to false to remove the minimize box.
		self.MinimizeBox = False            ## Set the accept button of the form to button1.
		self.StartPosition = FormStartPosition.CenterScreen
		self.AutoScroll = False
		self.ScrollBars = ScrollBars.Vertical
		self.ClientSize = System.Drawing.Size(500, 240)
		self.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show
		self.Name = "Title"#"Вихідні дані"
		self.Text = "Title"#"Вихідні дані"
		self.ResumeLayout(False)
		#
		self._label1 = System.Windows.Forms.Label()
		self._label2 = System.Windows.Forms.Label()
		self._label3 = System.Windows.Forms.Label()
		self._label4 = System.Windows.Forms.Label()
		self._label5 = System.Windows.Forms.Label()
		self._checkBox1 = System.Windows.Forms.CheckBox()
		self._label6 = System.Windows.Forms.Label()
		#
		self._label1.Location = System.Drawing.Point(20, 25)
		self._label1.Name = "label1"
		self._label1.Size = System.Drawing.Size(250, 23)
		self._label1.TabIndex = 1
		self._label1.Text = "Вибрана категорія" 
		self._label1.Font = System.Drawing.Font("Tahoma", 16, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0) 
		#
		self._label2.Location = System.Drawing.Point(20, 60)
		self._label2.Name = "label2"
		self._label2.Size = System.Drawing.Size(250, 23)
		self._label2.TabIndex = 1
		self._label2.Text = "Виберіть параметр" 
		self._label2.Font = System.Drawing.Font("Tahoma", 16, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0)  
		#
		self._label3.Location = System.Drawing.Point(20, 95)
		self._label3.Name = "label3"
		self._label3.Size = System.Drawing.Size(250, 23)
		self._label3.TabIndex = 1
		self._label3.Text = "Введіть дані"
		self._label3.Font = System.Drawing.Font("Tahoma", 16, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0)   
		#
		self._label4.Location = System.Drawing.Point(20, 130)
		self._label4.Name = "label4"
		self._label4.Size = System.Drawing.Size(250, 23)
		self._label4.TabIndex = 1
		self._label4.Text = "Дорівнює/Включає" 
		self._label4.Font = System.Drawing.Font("Tahoma", 16, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0)  
		#
		self._label5.Location = System.Drawing.Point(20, 165)
		self._label5.Name = "label5"
		self._label5.Size = System.Drawing.Size(100, 23)
		self._label5.TabIndex = 1
		self._label5.Text = "<,=,>"  
		self._label5.Font = System.Drawing.Font("Tahoma", 16, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0) 
		#
		self._comboBoxType = System.Windows.Forms.ComboBox()
		self._comboBoxType.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right
		self._comboBoxType.Location = System.Drawing.Point(280, 25)
		self._comboBoxType.Size = System.Drawing.Size(200, 20)
		self._comboBoxType.Items.AddRange(System.Array[System.Object](self._my_dict.keys()))
		self._comboBoxType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
		self._comboBoxType.SelectedIndexChanged += self.ComboBoxTypeSelectedIndexChanged
		self._comboBoxType.Font = System.Drawing.Font("Tahoma", 14, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0) 
		#
		self._comboBoxInstance = System.Windows.Forms.ComboBox()
		self._comboBoxInstance.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right
		self._comboBoxInstance.Location = System.Drawing.Point(280, 60)
		self._comboBoxInstance.Size = System.Drawing.Size(200, 20)
		self._comboBoxInstance.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
		self._comboBoxInstance.SelectionChangeCommitted += self.ComboBoxInstanceSelectedCommitted
		self._comboBoxInstance.Font = System.Drawing.Font("Tahoma", 14, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0)
		#
		self._text_value = System.Windows.Forms.TextBox()
		self._text_value.Location = System.Drawing.Point(280, 95)
		self._text_value.Name = "Значення"
		self._text_value.Text = ""
		self._text_value.Size = System.Drawing.Size(200, 20)
		self._text_value.Font = System.Drawing.Font("Tahoma", 14, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0) 
		#
		self._checkBox1.Name = "checkBox1"
		self._checkBox1.Location = System.Drawing.Point(380, 130)
		self._checkBox1.Size = System.Drawing.Size(30, 30)
		self._checkBox1.TabIndex = 0
		self._checkBox1.UseVisualStyleBackColor = True
		#
		self._cb1 = System.Windows.Forms.ComboBox()
		self.Controls.Add(self._cb1) # move to here
		self._cb1.Location = System.Drawing.Point(380, 165)
		self._cb1.Size = System.Drawing.Size(100, 20)
		self._cb1.DataSource = list_of_items_ravno
		self._cb1.DisplayMember = "Key"
		self._cb1.ValueMember = "Value"
		self._cb1.SelectedIndex = 1 # added #вибирає який по порядку елемент з'являється
		self._cb1.Font = System.Drawing.Font("Tahoma", 14, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0) 
		#
		self.button = System.Windows.Forms.Button()
		self.button.Text = 'Next'
		self.button.Location = Point(170,180)
		self.button.Width = 150
		self.button.Height = 35
		self.button.Click += self.button_click
		self.button.Font = System.Drawing.Font("Tahoma", 14, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0) 
		#
		self.Controls.Add(self._label1)
		self.Controls.Add(self._label2)
		self.Controls.Add(self._label3)
		self.Controls.Add(self._label4)
		self.Controls.Add(self._label5)
		self.Controls.Add(self._comboBoxType)
		self.Controls.Add(self._comboBoxInstance)
		self.Controls.Add(self._text_value)
		self.Controls.Add(self._checkBox1)
		self.Controls.Add(self.button)
		#
	def ComboBoxTypeSelectedIndexChanged(self, sender, e):
		self.choiceA = sender.SelectedItem
		self._comboBoxInstance.Items.Clear()
		values = self._my_dict.get(self.choiceA)
		values1 = [i.rsplit(self.choiceA)[1] for i in values]
		self._comboBoxInstance.Items.AddRange(System.Array[System.Object](values1))
		self._comboBoxInstance.DroppedDown = True
		return self._comboBoxInstance.Items
	def ComboBoxInstanceSelectedCommitted(self, sender, e):
		self.choiceB = sender.SelectedItem
 	def button_click(self, sender, event):
		self.out.append(self._comboBoxType.SelectedItem)#.Value)
		self.out.append(self._comboBoxInstance.SelectedItem)#.Value)
		self.out.append(self._text_value.Text)
		self.out.append(self._checkBox1.CheckState)
		self.out.append(self._cb1.SelectedItem.Value)
		self.Close()
objForm = MainForm(list_cats_all)
objForm.ShowDialog()
cats_out = [j for i,j in zip(list_cats,list_cats2) if objForm.out[0]==i][0]
parans_out = [j for i,j in zip(list_params,list_params1) if objForm.out[1]==i][0]
result = [cats_out,parans_out,objForm.out[2],objForm.out[3].value__,objForm.out[4]]
OUT = result

1 Like

Now add some colour and make it prettier :smiley:

2 Likes