Getting parameters in RevitAPI is a challenging task. I have had some serious headaches trying to wrap my head around the what, where and huh of the parameters. Maybe it’s because of the lack of proper documentation from Autodesk. I mean, I get it, they have a list of ALL MEMBERS, well…pff, it’s not always helpfull. An example would be the difference between ParametersMap and ParametersSet. The description on both is mindblowing. Now I really understand (not).
So, let’s dive into it.
Straight Forward
The easiest way I found to getting all the parameters that an instance may have, would be to actually get all the parameters from the instance it self, on top of which we add parameters of the loaded FamilySymbol (a FamilySymbol is a “created” FamilyType in RevitAPI terms) and also the parameters of the loaded Family (the loaded family is the Family Document which is an element in our working document).
NOTE : This is also the fastest (in terms of time needed for execution) method.
- In the below method I have a symbol Id, based on which i get the family and look for one instance in the working document (and it makes sense because why work with families that are not used, right?). In my case I made sure the symbol has an instance.
- I am concatenating all these parameters in one string. I made this to add these parameters to an excel file and compare results.
public Tuple<string, long> Test1(int symbolId) { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); FamilySymbol symbolElement = _document.GetElement(new ElementId(symbolId)) as FamilySymbol; Family family = symbolElement.Family; FamilyInstance instance = (new FilteredElementCollector(_document). OfClass(typeof(FamilyInstance)) .Cast() .Where(x => x.Symbol.Id.IntegerValue == symbolId)).FirstOrDefault(); //get parameters List familyParamNames = family .GetOrderedParameters() .ToList().Select(x => x.Definition.Name).ToList(); List instanceParams = instance .GetOrderedParameters() .Select(x => x.Definition.Name ).ToList(); List symbParams = symbolElement .GetOrderedParameters() .Select(x => x.Definition.Name ).ToList(); string allParameters = string.Join("\n", familyParamNames.Concat(instanceParams) .Concat(symbParams).Distinct().OrderBy(x => x)); stopWatch.Stop(); long elapsed = stopWatch.ElapsedMilliseconds; return Tuple.Create<string, long>(allParameters, elapsed); }
No in the image below, the column in Red represents all the parameters (for a Window) collected using the above methods. And as you can see, it’s plenty. The other columns represent data from the second method (which will be presented below) which are collected from multiple sources and it’s a more tedious work.
Now I know that getting the FamilyParameter straight from the family document gives us more information regarding the type of parameter(instance, reporting, etc). It all depends on the task at hand. For me, I use the element property of the Parameter to determine if it’s a Family/Symbol/Instance etc.
Inside the Family Document
Another way is to get the FamilyParameters . This involves actually opening the family and getting the parameters from the FamilyManager.
This would be like reading the parameters in the red side of the image below:
Note : In this method I am (also) concatenating results to be able to export them in the excel file:
public Tuple<string, long> Test2(int symbolId) { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); FamilySymbol symbolElement = _document.GetElement(new ElementId(symbolId)) as FamilySymbol; //getting the parameters that belong to the loaded symbol List symbParams = symbolElement .GetOrderedParameters() .Select(x => x.Definition.Name).ToList(); List familyDocumentParameters = new List(); if (symbolElement.Family.IsEditable) { Document familyDocument = _document.EditFamily(symbolElement.Family); Category category = symbolElement.Family.Category; FamilyManager familyManager = familyDocument.FamilyManager; //getting the parameters from the Family Document foreach (FamilyParameter parameter in familyManager.Parameters) { if (!symbParams.Contains(parameter.Definition.Name)) { familyDocumentParameters.Add(parameter.Definition.Name); } } familyDocument.Close(false); } stopWatch.Stop(); long elapsed = stopWatch.ElapsedMilliseconds; return Tuple.Create<string, long>(allParameters, elapsed); }
As you can see the square in red represents the list of parameters acquired so far using the second method. We still have some other unaccounted parameters, right?
There are some other BuiltInParameters that were not extracted in the method above, the Family parameters (which belong to the Family and are not visible in the FamilyManager.Parameters).
The following snippet gets parameters from the following sources:
- (In Red) the FamilySymbol.ParamertersMap
- (In Yellow) The Family.ParametersMap (if you open the FamilyEditor and the api targets the document directly, then you access it by using Family.OwnerDocument, see https://thebuildingcoder.typepad.com/blog/2009/07/get-and-set-family-category-and-parameters.html)
- (In Blue) The Family.ParametersSet
The ParametersMap has some extra Notions (like the FamilyName, Category, etc) more then the ParametersSet. So i guess it’s for another use.
And if you are wondering why Red, Yellow and Blue in my choice of colors? It’s because:
So, the code :
And the result, in the squares below, add-up to the full list of parameters that were determined inthe first method
Performance
I did a simple test (using a StopWatch). And it turns out that opening a Family and reading the parameters (second method) it’s slower then looking for one instance in the document and getting all it’s parameters. But this test was made on a Sample Revit Model so I don’t have many instances.