Search code examples
c#revit-apirevit

Filtering by a Family in Revit API


For a while now I have been looking for a way to filter elements by their family. For example, I want all of the elements that are of family Junction Boxes - Load. I am somewhat new to the Revit API, and I do know about category filters and even a family instance filter. But I do not understand how I get the family symbol for the Junction Boxes - Load family, for example. Is there even a good way of doing this? Or am I better off filtering specific Types within the family? If so, how would I go about doing this?


Solution

  • Jacob,

    Jeremy's answer is the right one. Here's an example of code that could be used to get all Family Instances of certain Family name:

    The efficient way that Jeremy mentioned would be to use the Parameter Filter:

    var famType = new FilteredElementCollector(m_doc)
        .OfClass(typeof(Family)) // This is called a class filter
        .FirstOrDefault(x => x.Name == "YourFamilyName");
    
    if (famType != null)
    {
        const BuiltInParameter testParam = BuiltInParameter.ELEM_FAMILY_PARAM;
        var pvp = new ParameterValueProvider(new ElementId((int)testParam));
        var fnrv = new FilterNumericEquals();
        var ruleValId = famType.Id;
        var paramFr = new FilterElementIdRule(pvp, fnrv, ruleValId);
        var epf = new ElementParameterFilter(paramFr);
    
        var results = new FilteredElementCollector(m_doc)
            .OfClass(typeof(FamilyInstance))
            .WherePasses(epf)
            .ToElements();
    }
    

    The less efficient way would be to do this:

    var result = new FilteredElementCollector(m_doc)
        .OfClass(typeof(FamilyInstance))
        .Cast<FamilyInstance>()
        .Where(x => x.get_Parameter(BuiltInParameter.ELEM_FAMILY_PARAM).AsValueString() == "YourFamilyName");
    

    I know that Jeremy mentioned that the second method would be less efficient, but I am personally not entirely sure. The ElementParameterFilter is a Slow Filter which expands all of the elements in memory anyways. Event though it's coupled with two Quick Filters for Family and FamilyInstance selection, that's still a considerable overhead as opposed to the more direct approach that you can take using LINQ.

    You also asked about being able to select FamilySymbol

    var famType = new FilteredElementCollector(m_doc)
            .OfClass(typeof(FamilySymbol))
            .FirstOrDefault(x => x.Name == "YourFamilyTypeName");