Description
When it comes to Revit we can say that parameters are one of the most important features there is, it allows users to dynamically update and change the model according to parameter values. This kind of flexibility is what drove many companies to chose Revit over other BIM providers.
When developing Revit Add-ins that require working with parameters it’s very important to really pay attention to the unit types and project units. The user will most likely want that your application to be synced with his active document.
If you have worked with the mathematical software Mathcad, you might remember a very useful functionality of it, the ability to define a parameter with a unit type and the ability to represent and use that parameter with any variations of that unit type (An area defined in square meters is easily represented in square cm or square ft).
From this point of view Revit works similarly. When a parameter with a UnitType is defined Revit will internally store a value that is converted in the default Unit Type for that Value. E.G. A unit type UT_Length will be always internally store in feet while it’s representation will vary depending on the users options. This option is called DisplayUnitType (DUT)
Getting the parameters
So how to actually get a parameter? Well that’s pretty straightforward. I’ve shown you in a previous article how to use the BuiltInParameter enumeration to get a certain parameter.
For this example I’ve considered to work with a Room type and present the different options of getting parameters for this Element. Note that the techniques are the same for all Revit elements (even for Families and FamilyTypes)
Room room = new FilteredElementCollector(Initializer.DbDocument) .WherePasses(new RoomFilter()) .Cast() .FirstOrDefault();
- One option to getting a parameter is by it’s association to the BuildInParameter
Parameter roomName = room.get_Parameter(BuiltInParameter.ROOM_NAME);
- Another option is by providing the name of the parameter you want to retrieve.
List commentParameter = room.GetParameters("Comments").ToList()
- And we can of course get all the parameters in an ordered list
List paramters = room.GetOrderedParameters().ToList()
In the debugger you can see the differences :
Parameter insights
The parameter object is actually made by two components.
The first component is the parameter it self that stores the internal value, the display unit type (which is in fact the unit type set up by the user in the active model as I will show you later on), the storage type which is very important as it tells us what type the actual parameter stores.
The storage type tells us of the value is integer, double, text, element id or none which flags an invalid type.
The second component of a parameter is the definiton which can be accessed from the parameter object. The definition is the baseline of a parameter and it contains the base unit type and the parameter type.
If you are a bit confused regarding all these types, here’s a summary:
- Storage type – defines the type of the value stored (string, int, double, etc)
- Unit Type – defines the underlying (default unit) for a speficic parameter type (like feet for length)
- Display Unit Type – determines how will the value be represented (as meters or centimeters)
- ParameterType – the abstract interpretation of the what the parameter represents (area, length, force)
Working with parameters
If you are working with parameters here are some tips:
- If you are iterating a set of parameters, you can check if a user can modify it (not read only) and you should check if it’s a valid storage type
foreach (Parameter parameter in paramters) { //filtering out the parameters that the user can't modify or are invalid if (!parameter.UserModifiable || parameter.StorageType == StorageType.None) continue; }
- You can use the storage type to determine how to get the values
string valueRepr = string.Empty; switch (parameter.StorageType) { case StorageType.Double: valueRepr = parameter.AsDouble().ToString(); break; case StorageType.ElementId: valueRepr = parameter.AsElementId().IntegerValue.ToString(); break; case StorageType.Integer: valueRepr = parameter.AsInteger().ToString(); break; default: valueRepr = parameter.AsValueString(); break; }
- Setting the value of the parameter is easy. Just make sure is not read only
string valueRepr = string.Empty; switch (parameter.StorageType) { case StorageType.Double: parameter.Set(100); break; case StorageType.ElementId: parameter.Set(new ElementId(123)); break; case StorageType.Integer: parameter.Set(123); break; default: parameter.Set("Hello"); break; }
Properly display the unit type
There are several issues when displaying a parameter’s value
- We want to display it according to the settings in the project’s unit. We have this information in the display unit type that we access from the parameter and this is the same as the one set in project units, and to test this we can also get the project display unit type for this parameter on compare the both.
- The parameter stores a value in the default unit type. To convert it to the actual displayed value. To achieve this we will use the UnitUtils class
- We might want to show the user the unit type representation (e.g. “100 mm”). Again Revit provides lots of helpers and the one we will use is LabelUtils