I am an architect who grew to love coding through Revit. But unfortunately since still being an ultimate noob, I would need some help from anyone willing to jump in. I am also Stackoverflow noob, so I dont know if it is even OK and excepted in the community to post a questions like these which are more tutoring ones then problem solving. But anyway, here it goes: I am trying to create an app which will be able to delete multiple parameters from Revit family editor at the same time. I have succeeded with C#, but since I want to transfer to Python due to being an easier to get into as beginner I am doing a lot of browsing but with no help due to a limited OOP knowledge. How can I display Family parameter name in a Listbox or if I alredy have string names in listbox, how can I compare selected items with actual parameters from FamilyParameterSet?
I have a start code where I am able to collect all parameters from Family manager. I cast it to List. Then one options is to use Name attribute of the parameter to be listed in listbox, but I do not have knowledge to get back and check out list or to loop the list to compare names from the parameter set to ones being selected from listbox. So I went to another option of putting directly Family parameters in listbox, but I am then not able to display actual Name attribute. This C# code might help me, but I do not know how to recreate it in Python, since my OOP experience is really poor. Items on ListBox show up as a class name
doc = __revit__.ActiveUIDocument.Document
mgr = doc.FamilyManager;
fps = mgr.Parameters;
paramsList=list(fps)
senderlist =[]
class IForm(Form):
def __init__(self):
self.Text = "Remove multiple parameters"
lb = ListBox()
lb.SelectionMode = SelectionMode.MultiSimple
for n in fps:
lb.Items.Add(n.Definition.Name)
lb.Dock = DockStyle.Fill
lb.SelectedIndexChanged += self.OnChanged
self.Size = Size(400, 400)
self.CenterToScreen()
button = Button()
button.Text = "Delete Parameters"
button.Dock = DockStyle.Bottom
button.Click += self.RemoveParameter
self.Controls.Add(button)
def OnChanged(self, sender, event):
senderlist.append(sender.SelectedItem)
def RemoveParameter(self,sender,event):
for i in paramsList:
if i.Definition.Name in senderlist:
t = Transaction(doc, 'This is my new transaction')
t.Start()
mgr.RemoveParameter(i.Id)
t.Commit()
Application.Run(IForm())
I need for function RemoveParameter to have all .Id proportes of the Family parameters in order to remove them from the Family parameter set. In the start of the code (for guys which do not know Revit API) "fps" means FamilyParameterSet which is cast to Python list "paramsList".So I need to remove member of the FPS from items selected in listbox.
Your journey from Revit to code is a familiar one!
First, looks like there are some hangovers in your code from C#. There are a couple of key shifts from C# to Python that you need to bear in mind - in your case there are two lines that need to be indented, as per the error when you run the code:
Syntax Error: expected an indented block (line 17)
Syntax Error: expected an indented block (line 39)
The rule of thumb is that indents are needed after colons :
which also makes code more readable. Also there are some semi-colons ;
in the first few lines - no need for them!
Otherwise the code was pretty much there, Ive added comments in your code below:
# the Winforms library first needs to be referenced with clr
import clr
clr.AddReference("System.Windows.Forms")
# Then all the Winforms components youre using need to be imported
from System.Windows.Forms import Application, Form, ListBox, Label, Button, SelectionMode, DockStyle
doc = __revit__.ActiveUIDocument.Document
mgr = doc.FamilyManager
fps = mgr.Parameters
paramsList=list(fps)
# senderlist = [] moved this into the Form object - welcome to OOP!
class IForm(Form):
def __init__(self):
self.Text = "Remove multiple parameters"
self.senderList = []
lb = ListBox()
lb.SelectionMode = SelectionMode.MultiSimple
lb.Parent = self # this essentially 'docks' the ListBox to the Form
for n in fps:
lb.Items.Add(n.Definition.Name)
lb.Dock = DockStyle.Fill
lb.SelectedIndexChanged += self.OnChanged
self.Size = Size(400, 400)
self.CenterToScreen()
button = Button()
button.Text = "Delete Parameters"
button.Dock = DockStyle.Bottom
button.Click += self.RemoveParameter
self.Controls.Add(button)
def OnChanged(self, sender, event):
self.senderList.append(sender.SelectedItem)
def RemoveParameter(self,sender,event):
for i in paramsList:
if i.Definition.Name in self.senderList:
t = Transaction(doc, 'This is my new transaction')
t.Start()
# wrap everything inside Transactions in 'try-except' blocks
# to avoid code breaking without closing the transaction
# and feedback any errors
try:
name = str(i.Definition.Name)
mgr.RemoveParameter(i) # only need to supply the Parameter (not the Id)
print 'Parameter deleted:',name # feedback to the user
except Exception as e:
print '!Failed to delete Parameter:',e
t.Commit()
self.senderList = [] # clear the list, so you can re-populate
Application.Run(IForm())
From here, additional functionality is just polishing it up for users:
ListBox
BuiltIn
parameters that cant be deleted (try deleting one and see the error it throws)Let me know how this works!