Managing family types and parameters

Managing family types and parameters

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.

Getting Types in a Family

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

Editing FamilyTypes

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;
    }
}
The FamilyManager class provides access to all the family parameters. This includes family built-in parameters, category built-in parameters and shared parameters associated to the family types. There are two ways to get the family parameters:
  • Parameters property - gets all parameters in the family
  • GetParameters() - gets all the parameters in the family in order in which they appear in the Revit UI

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.

The simplest way to reorder parameters is using the FamilyManager.SortParameters() method, which takes a parameter indicating the desired sort order. The sample below sorts the parameters in ascending order.
Code Region: Sort family parameters
private void DisplayParametersInAscendingOrder(Document familyDoc)
{
    FamilyManager familyManager = familyDoc.FamilyManager;
    familyManager.SortParameters(ParametersOrder.Ascending);
}
Note: The sort is a one-time operation. When new parameters are added they will not be automatically sorted.

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.