Family documents provide access to the FamilyManager property. The FamilyManager class provides access to family types and parameters. Using this class you can add and remove types, add and remove family and shared parameters, set the value for parameters in different family types, and define formulas to drive parameter values.
The FamilyManager can be used to iterate through the types in a family, as the following example demonstrates.
Code Region 13-11: Getting the types in a family |
public void GetFamilyTypesInFamily(Document familyDoc) { if (familyDoc.IsFamilyDocument) { FamilyManager familyManager = familyDoc.FamilyManager; // get types in family string types = "Family Types: "; FamilyTypeSet familyTypes = familyManager.Types; FamilyTypeSetIterator familyTypesItor = familyTypes.ForwardIterator(); familyTypesItor.Reset(); while (familyTypesItor.MoveNext()) { FamilyType familyType = familyTypesItor.Current as FamilyType; types += "\n" + familyType.Name; } TaskDialog.Show("Revit",types); } } |
Figure 53: Family types in Concrete-Rectangular-Column family
FamilyManager provides the ability to iterate through existing types in a family, and add and modify types and their parameters.
The following example shows how to add a new type, set its parameters and then assign the new type to a FamilyInstance. Type editing is done on the current type by using the Set() function. The current type is available from the CurrentType property. The CurrentType property can be used to set the current type before editing, or use the NewType() function which creates a new type and sets it to the current type for editing.
Note that once the new type is created and modified, Document.LoadFamily() is used to load the family back into the Revit project to make the new type available.
Code Region 13-12: Editing Family Types |
public void EditFamilyTypes(Document document, FamilyInstance familyInstance) { // example works best when familyInstance is a rectangular concrete element if ((null == document) || (null == familyInstance.Symbol)) { return; // invalid arguments } // Get family associated with this Family family = familyInstance.Symbol.Family; if (null == family) { return; // could not get the family } // Get Family document for family Document familyDoc = document.EditFamily(family); if (null == familyDoc) { return; // could not open a family for edit } FamilyManager familyManager = familyDoc.FamilyManager; if (null == familyManager) { return; // cuould not get a family manager } // Start transaction for the family document using (Transaction newFamilyTypeTransaction = new Transaction(familyDoc, "Add Type to Family")) { int changesMade = 0; newFamilyTypeTransaction.Start(); // add a new type and edit its parameters FamilyType newFamilyType = familyManager.NewType("2X2"); if (newFamilyType != null) { // look for 'b' and 'h' parameters and set them to 2 feet FamilyParameter familyParam = familyManager.get_Parameter("b"); if (null != familyParam) { familyManager.Set(familyParam, 2.0); changesMade += 1; } familyParam = familyManager.get_Parameter("h"); if (null != familyParam) { familyManager.Set(familyParam, 2.0); changesMade += 1; } } if (2 == changesMade) // set both paramaters? { newFamilyTypeTransaction.Commit(); } else // could not make the change -> should roll back { newFamilyTypeTransaction.RollBack(); } // if could not make the change or could not commit it, we return if (newFamilyTypeTransaction.GetStatus() != TransactionStatus.Committed) { return; } } // now update the Revit project with Family which has a new type LoadOpts loadOptions = new LoadOpts(); // This overload is necessary for reloading an edited family // back into the source document from which it was extracted family = familyDoc.LoadFamily(document, loadOptions); if (null != family) { // find the new type and assign it to FamilyInstance ISet<ElementId> familySymbolIds = family.GetFamilySymbolIds(); foreach (ElementId id in familySymbolIds) { FamilySymbol familySymbol = family.Document.GetElement(id) as FamilySymbol; if ((null != familySymbol) && familySymbol.Name == "2X2") { using (Transaction changeSymbol = new Transaction(document, "Change Symbol Assignment")) { changeSymbol.Start(); familyInstance.Symbol = familySymbol; changeSymbol.Commit(); } break; } } } } class LoadOpts : IFamilyLoadOptions { public bool OnFamilyFound(bool familyInUse, out bool overwriteParameterValues) { overwriteParameterValues = true; return true; } public bool OnSharedFamilyFound(Family sharedFamily, bool familyInUse, out FamilySource source, out bool overwriteParameterValues) { source = FamilySource.Family; overwriteParameterValues = true; return true; } } |
When using the GetParameters() method, the Revit UI order is determined first by group and next by the order of the individual parameters.
Family parameters can be reordered (within their groups) from the API for a given family (with the exception of the Rebar Shape family which does not support reordering parameters). This allows for parameters to be presented to the user in the most logical order. Sorting only affects visible parameters within the same parameter group. Parameters that belong to different groups will remain separated, and the groups' order will not be affected.
Code Region: Sort family parameters |
---|
private void DisplayParametersInAscendingOrder(Document familyDoc) { FamilyManager familyManager = familyDoc.FamilyManager; familyManager.SortParameters(ParametersOrder.Ascending); } |
For more control over how parameters are sorted, use the FamilyManager.ReorderParameters() method which takes a list of family parameters in the new order. This list must include all the parameters returned by the GetParameters() method, including any invisible parameters, or an exception will be thrown.