WinForm with checkboxes, keys and values

Hello Dynamo friends :slight_smile:

I want to build a WinForm that displays a list of keys, lets me make a selection and gives the values as a result. I found the following thread and stole some code from @c.poupin :smiley:

This code gives me just the keys as output, so i wrote a piece of code that gets the values from there.

KeyList = IN[0]
ValueList = IN[1]
Selection = IN[2]

Result=[]

for i in Selection:
    Index = KeyList.index(i)
    Value = ValueList[Index]
    Result.append(Value)
    
OUT = Result

My problem is now that i can´t get this to work in a single python node because my WinForm output seems to be a collection and not a list :open_mouth: So how can i make a list out of it?

import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry 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 *

class Form24(Form):
	def __init__(self, lstSchedule):
		self._lstSchedule = lstSchedule
		self.out = []
		self.InitializeComponent()
	
	def InitializeComponent(self):
		self._checkedListBox1 = System.Windows.Forms.CheckedListBox()
		self._checkBoxSelectAll = System.Windows.Forms.CheckBox()
		self._button1 = System.Windows.Forms.Button()
		self.SuspendLayout()
		# 
		# checkedListBox1
		# 
		self._checkedListBox1.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right
		self._checkedListBox1.FormattingEnabled = True
		self._checkedListBox1.CheckOnClick = True
		self._checkedListBox1.Location = System.Drawing.Point(12, 30)
		self._checkedListBox1.Name = "checkedListBox1"
		self._checkedListBox1.DataSource = self._lstSchedule 
		#self._checkedListBox1.Items.AddRange(System.Array[System.Object](self._lstSchedule))
		self._checkedListBox1.DisplayMember = "Name"
		self._checkedListBox1.Size = System.Drawing.Size(260, 244)
		self._checkedListBox1.TabIndex = 0
		# 
		# checkBoxSelectAll
		# 
		self._checkBoxSelectAll.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left
		self._checkBoxSelectAll.Location = System.Drawing.Point(12, 291)
		self._checkBoxSelectAll.Name = "checkBoxSelectAll"
		self._checkBoxSelectAll.Size = System.Drawing.Size(104, 24)
		self._checkBoxSelectAll.TabIndex = 1
		self._checkBoxSelectAll.Text = "All/None"
		self._checkBoxSelectAll.UseVisualStyleBackColor = True
		self._checkBoxSelectAll.CheckedChanged += self.CheckBoxSelectAllCheckedChanged
		# 
		# button1
		# 
		self._button1.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right
		self._button1.Location = System.Drawing.Point(191, 289)
		self._button1.Name = "button1"
		self._button1.Size = System.Drawing.Size(75, 27)
		self._button1.TabIndex = 2
		self._button1.Text = "OK"
		self._button1.UseVisualStyleBackColor = True
		self._button1.Click += self.Button1Click
		# 
		# Form24
		# 
		self.ClientSize = System.Drawing.Size(284, 334)
		self.Controls.Add(self._button1)
		self.Controls.Add(self._checkBoxSelectAll)
		self.Controls.Add(self._checkedListBox1)
		self.Name = "Title"
		self.Text = "Title"
		self.ResumeLayout(False)


	def CheckBoxSelectAllCheckedChanged(self, sender, e):
		for i in range(self._checkedListBox1.Items.Count):
			self._checkedListBox1.SetItemChecked(i, sender.Checked) 

	def Button1Click(self, sender, e):
		self.out = self._checkedListBox1.CheckedItems
		self.Close()
	
toList = lambda x : x if hasattr(x, '__iter__') else [x]

#Preparing input from dynamo to revit
lstSchedules = toList(UnwrapElement(IN[0]))
ValueList = toList(UnwrapElement(IN[1]))
objForm = Form24(lstSchedules)
objForm.ShowDialog()

KeyList = objForm.out

Result=[]

for Key in KeyList:
    Index = KeyList.index(Key)
    Value = ValueList[Index]
    Result.append(Value)
    
OUT = Result
1 Like

Hi @gerhard.p ,

I don’t understand what you trying to do.
Do you need the outputs of the selected values?

Hello Jan,

i want to do the standard key/value thing, like datashapes does it.
Here an example with RibbonTabs as values and names as keys:

Keys are just used to identify the values, i want to get the corresponding value (RibbonTab) as output.

As cirils code only got me the “keys” as output I wanted to use get index and get item at index methods to get my values, but there for sure must be a better way? I searched through the datashapes code but couldn´t find what i need.

Hi,
you can use a dictionary or a DataTable

example

import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry 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.Data')
from System.Data import *

class Form24(Form):
	def __init__(self, lstSchedule, lstValue):
		self._tableData = DataTable("Data")
		self._tableData.Columns.Add("Key", System.String)
		self._tableData.Columns.Add("Value", System.Object)
		# populate dataTable
		[self._tableData.Rows.Add(key_, value_ ) for key_, value_ in zip(lstSchedule, lstValue)]
		self.out = []
		self.InitializeComponent()
	
	def InitializeComponent(self):
		self._checkedListBox1 = System.Windows.Forms.CheckedListBox()
		self._checkBoxSelectAll = System.Windows.Forms.CheckBox()
		self._button1 = System.Windows.Forms.Button()
		self.SuspendLayout()
		# 
		# checkedListBox1
		# 
		self._checkedListBox1.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right
		self._checkedListBox1.FormattingEnabled = True
		self._checkedListBox1.CheckOnClick = True
		self._checkedListBox1.Location = System.Drawing.Point(12, 30)
		self._checkedListBox1.Name = "checkedListBox1"
		self._checkedListBox1.DataSource = self._tableData 
		self._checkedListBox1.DisplayMember = "Key"
		self._checkedListBox1.Size = System.Drawing.Size(260, 244)
		self._checkedListBox1.TabIndex = 0
		# 
		# checkBoxSelectAll
		# 
		self._checkBoxSelectAll.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left
		self._checkBoxSelectAll.Location = System.Drawing.Point(12, 291)
		self._checkBoxSelectAll.Name = "checkBoxSelectAll"
		self._checkBoxSelectAll.Size = System.Drawing.Size(104, 24)
		self._checkBoxSelectAll.TabIndex = 1
		self._checkBoxSelectAll.Text = "All/None"
		self._checkBoxSelectAll.UseVisualStyleBackColor = True
		self._checkBoxSelectAll.CheckedChanged += self.CheckBoxSelectAllCheckedChanged
		# 
		# button1
		# 
		self._button1.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right
		self._button1.Location = System.Drawing.Point(191, 289)
		self._button1.Name = "button1"
		self._button1.Size = System.Drawing.Size(75, 27)
		self._button1.TabIndex = 2
		self._button1.Text = "OK"
		self._button1.UseVisualStyleBackColor = True
		self._button1.Click += self.Button1Click
		# 
		# Form24
		# 
		self.ClientSize = System.Drawing.Size(284, 334)
		self.Controls.Add(self._button1)
		self.Controls.Add(self._checkBoxSelectAll)
		self.Controls.Add(self._checkedListBox1)
		self.Name = "Title"
		self.Text = "Title"
		self.ResumeLayout(False)


	def CheckBoxSelectAllCheckedChanged(self, sender, e):
		for i in range(self._checkedListBox1.Items.Count):
			self._checkedListBox1.SetItemChecked(i, sender.Checked) 

	def Button1Click(self, sender, e):
		self.out = [row['Value'] for row in self._checkedListBox1.CheckedItems]
		self.Close()
	
toList = lambda x : x if hasattr(x, '__iter__') else [x]

#Preparing input from dynamo to revit
lstSchedules = toList(UnwrapElement(IN[0]))
ValueList = toList(UnwrapElement(IN[1]))
objForm = Form24(lstSchedules, ValueList)
objForm.ShowDialog()

Result = objForm.out

OUT = Result

Note:
pay attention currently hasattr(x, '__iter__') does not work well with Cpython3/Pythonnet

2 Likes

Hello Cyril,

OK, you created a table with rows and columns, and then filled the rows with the keys and values which are zipped together. In the end you get the value for every checked row. Thank you very much! :slight_smile:

I changed the inputs to avoid problems with the “iter” function:

#Preparing input from dynamo to revit

if isinstance(IN[0],list):
	lstSchedules = UnwrapElement(IN[0])
else:
	lstSchedules = [UnwrapElement(IN[0])]
	
if isinstance(IN[1],list):
	ValueList = UnwrapElement(IN[1])
else:
	ValueList = [UnwrapElement(IN[1])]

objForm = Form24(lstSchedules, ValueList)
objForm.ShowDialog()

Result = objForm.out

OUT = Result

image

1 Like