How do we get all Revit User Interface Project Browser's Families ?

How do we get all Revit User Interface Project Browser's Families ?

Anonymous
Not applicable
3,136 Views
8 Replies
Message 1 of 9

How do we get all Revit User Interface Project Browser's Families ?

Anonymous
Not applicable

It is very confusing that the Family Class represents only the custom families.

Below are the Categories from an out of the box Revit Construction Template, showing which of them are associated to the Family Class elements.

Revit API - Family Class Categories.jpg 

How can I use a Filter Element Collector to get the rest of the above Project Browser's Families (System Families), such as ceiling, walls etc ?

 

The Revit API Family Class Documentation explains that it represents only custom families and not system Revit Families. Why is that?? - If that is how the family is defined why those are still called families in Revit User Browser Interface? This seems to be concussing.

Revit API - Family Class.jpg

 

Below the code I used, to picks the project Browser families. Is there any way to modify the following code and get all families shown in the Revit User Interface Project Browser?

 

Document doc = commandData.Application.ActiveUIDocument.Document;
FilteredElementCollector ElementCollector = new FilteredElementCollector(doc);
ElementClassFilter FamilyFilter = new ElementClassFilter(typeof(Family));
ElementCollector.WherePasses(FamilyFilter);

foreach (Element i in ElementCollector)
{
  Debug.Print((i as Autodesk.Revit.DB.Family).FamilyCategory.Name);
}

 

 

Any advice will be really appreciated.

 

Regards,

Alexandros

0 Likes
3,137 Views
8 Replies
Replies (8)
Message 2 of 9

kraftwerk15
Advocate
Advocate

100% don't know if this would work, but could you keep what you have there and then add an excluding FEC to your first FEC?

 

Like:

Document doc = commandData.Application.ActiveUIDocument.Document;
FilteredElementCollector ElementCollector = new FilteredElementCollector(doc);
ElementClassFilter FamilyFilter = new ElementClassFilter(typeof(Family));
FilteredElementCollector newishCollector = ElementCollector.WherePasses(FamilyFilter);

FilteredElementCollector reallyNewishCollector = ElementCollector.Excluding(newishCollector.ToElementIds());

As I said, I don't know what this returns, but it would be interesting to see what the collection looks like. (Don't have VS up at the moment).

 

If that didn't work, you could declare your categories explicitly and just get new FEC per each individual Built-In-Category using:

Document doc = commandData.Application.ActiveUIDocument.Document;
FilteredElementCollector ElementCollector = new FilteredElementCollector(doc);

FilteredElementCollector first = ElementCollector.OfCategory(BuiltInCategory.OST_Walls);
FilteredElementCollector second = ElementCollector.OfCategory(BuiltInCategory.OST_Floors);
 *** Or something like this, I'm typing it all from memory. ***
0 Likes
Message 3 of 9

RPTHOMAS108
Mentor
Mentor

You could probably think of what is listed in the project browser under families as a list of ElementType sorted and grouped by category name then ElementType.FamilyName (then finally ElementType.Name).

 

From ElementType you can see if it casts to FamilySymbol and if so you can then get the Family from that FamilySymbol.Family. In terms of those that are not FamilySymbols they have no Family in reality, so no further place to go (apart from functionality on their ElementType inherited class or static methods on utility classes elsewhere.).

 

The API reflects the internal workings (some aligned to non-API objects and some and some created solely for the API). Whilst the UI reflects how all those things are simplified to the user. Confusion could arise in numerous other ways i.e. the FamilyType class is a class used within the family environment not the project where FamilySymbol is used instead. I think to a degree you have to let go of such discrepancies because they will likely never align (in terms of how an end user recognises them).

0 Likes
Message 4 of 9

RPTHOMAS108
Mentor
Mentor

Some further notes on the above:

 

  1. Some ElementTypes do not have a Category e.g. Arrow Heads. So the first filter should remove all ElementTypes with a Category = null (these aren't  things that appear in the project browser anyway).
  2. Where the Category.CategoryType = Annotation, it will go in the 'Annotation Symbols' branch of the project browser rather than under its category name i.e. there are various tag categories but they all end up under this branch.
  3. The property Category.IsVisibleInUI will allow you to filter out some Categories that shouldn't appear.
  4. The property ElementType.CanBeRenamed should allow the filtering of some items following the logic that all ElementTypes in the project browser can be renamed, as far as I know.

 

After filtering for all of these items you'll still find certain things that shouldn't be there e.g. 'Revision Clouds' and 'GridTypes', 'Color Fill Legend'.

 

Would be good if there was a property ElementType.ShownInProjectBrowser.

Category.IsVisibleInUI is a bit vague since most things are visible in some part of the UI (otherwise how do we access them) e.g. wire temperatures. Would be good to know what part of the UI the 'IsVisibleInUI' relates to. I would have expected revision clouds not to return true for this (if it was related to the project browser).

 

 

Message 5 of 9

Anonymous
Not applicable

@RPTHOMAS108 Thanks a lot for your suggestions!! Unfortunately the Category.IsVisibleInUI parameter seems to be confusing for me (the description "Identifies if the category is visible to the user and should be displayed in UI." which currently exist at the Revit API is not very clear). Also, the ElementType.CanBeRenamed property could be also true for ElementType Elements which do not exist in the Project Browser, therefore this value is not helpful here.

 

I wish there was a method (as you mentioned something like ElementType.ShownInProjectBrowser) to select all elements that exist in the Project Browser under the Families. And, as I previously mentioned, the "Families" Terminology in the Revit User Interface Project Browser is contradicting the Revit API Family Class - This wil be nice if it could be rectified in the Revit next Versions.  

 

For now, I found the solution below to select all Project Browser Elements, I hope this to be useful for others.

 

 

 

FilteredElementCollector ElementCollector_FamilyAndSystemTypes = new FilteredElementCollector(doc).WherePasses(new ElementClassFilter(typeof(Family)));
ElementCollector_FamilyAndSystemTypes.UnionWith(new FilteredElementCollector(doc)
.WherePasses(new ElementClassFilter(typeof(Autodesk.Revit.DB.Architecture.ContinuousRailType))));
ElementCollector_FamilyAndSystemTypes.UnionWith(new FilteredElementCollector(doc)
.WherePasses(new ElementClassFilter(typeof(Autodesk.Revit.DB.Architecture.CutMarkType))));
ElementCollector_FamilyAndSystemTypes.UnionWith(new FilteredElementCollector(doc)
.WherePasses(new ElementClassFilter(typeof(Autodesk.Revit.DB.Architecture.RailingType))));
ElementCollector_FamilyAndSystemTypes.UnionWith(new FilteredElementCollector(doc)
.WherePasses(new ElementClassFilter(typeof(Autodesk.Revit.DB.Architecture.StairsLandingType))));
ElementCollector_FamilyAndSystemTypes.UnionWith(new FilteredElementCollector(doc)
.WherePasses(new ElementClassFilter(typeof(Autodesk.Revit.DB.Architecture.StairsPathType))));
ElementCollector_FamilyAndSystemTypes.UnionWith(new FilteredElementCollector(doc)
.WherePasses(new ElementClassFilter(typeof(Autodesk.Revit.DB.Architecture.StairsRunType))));
ElementCollector_FamilyAndSystemTypes.UnionWith(new FilteredElementCollector(doc)
.WherePasses(new ElementClassFilter(typeof(Autodesk.Revit.DB.Architecture.StairsType))));
ElementCollector_FamilyAndSystemTypes.UnionWith(new FilteredElementCollector(doc)
.WherePasses(new ElementClassFilter(typeof(Autodesk.Revit.DB.GroupType))));
ElementCollector_FamilyAndSystemTypes.UnionWith(new FilteredElementCollector(doc)
.WherePasses(new ElementClassFilter(typeof(Autodesk.Revit.DB.HostObjAttributes))));
ElementCollector_FamilyAndSystemTypes.UnionWith(new FilteredElementCollector(doc)
.WherePasses(new ElementClassFilter(typeof(Autodesk.Revit.DB.InsertableObject))));
ElementCollector_FamilyAndSystemTypes.UnionWith(new FilteredElementCollector(doc)
.WherePasses(new ElementClassFilter(typeof(Autodesk.Revit.DB.Plumbing.PipeInsulationType))));
ElementCollector_FamilyAndSystemTypes.UnionWith(new FilteredElementCollector(doc)
.WherePasses(new ElementClassFilter(typeof(Autodesk.Revit.DB.Plumbing.PipingSystemType))));
ElementCollector_FamilyAndSystemTypes.UnionWith(new FilteredElementCollector(doc)
.WherePasses(new ElementClassFilter(typeof(Autodesk.Revit.DB.Mechanical.DuctLiningType))));

 

 

 

I haven't completed the list as I was more interested on the Revit Architectural Elements but as I understood, sadly, this is the only way to go.

 

Below an Updated Project Browser Screen capture, shows the quicker way to quickest filter each one of the Elements, Family Class, ElementTypes Class etc.

 

Highlighted:

in Red - elements inherited by Family class,

in Blue - elements inherited by ElementType class,

in Yellow - BuiltInParameter Enumeration,

in Purple -  TilePatternsBuiltIn Revit API Enumerations

 

Project Browser - Element Types and Families.jpg

0 Likes
Message 6 of 9

RPTHOMAS108
Mentor
Mentor

I'm not sure what you mean in terms of the Red items?

 

Structural Framing = OST_StructuralFraming (you note as red) similar to the form of:

Structural Columns = OST_StructuralColumns (you note as yellow)

Both are instances of FamilyInstance and ElementType of FamilySymbol

 

Structural Beam Systems = OST_StructuralFramingSystem

(BeamSystemType, inherited from ElementType) (System Family so not Red)

 

Structural Foundations = OST_StructuralFoundations

FloorType, inherited from ElementType (for Foundation Slab)(System Family) or 

WallFoundationType, inherited from ElementType (for Wall Foundation)(System Family) or

FamilySymbol, inherited from ElementType (for isolated foundations)(Loadable Family)

 

This is why I say as a starting point: start with Category, then ElementType then see what is missing and what shouldn't be there e.g. Revision Clouds. I think there is no clean way to build a comparable list but generally every item has a category and every item has an ElementType.

 

In general we know there are loadable families (FamilySymbol) and system families (other form of ElementType).

 

TilePattern (purple) is inherited from ElementType, was missing from my list because it can't be renamed. There may also be an enum of values for it just like there is an enum of ViewTypes but the items you click on in the Project Browser and then look at in Revit lookup for it are of the TilePattern class.

 

Here is another interesting thing: OST_StackedWalls: IsVisibleInUI=False but I see it in the project browser under walls.

0 Likes
Message 7 of 9

RPTHOMAS108
Mentor
Mentor

From what's new section of 2020 RevitAPI.chm

 

"Category.IsVisibleInUI
returns true if the category should be visible to the user in lists of categories in the Revit user interface (dialogs such as Visibility Graphics or View Filters)."

 

I'll just make the suggestion that the property name is a bit vague and the meaning of it will be lost over time unless it is added in this form above to the RevitAPI.chm (the bit that doesn't change each year).

 

What is wrong with Category.IsInViewFiltersUI

We already have Category.AllowsVisibilityControl(View)

 

0 Likes
Message 8 of 9

Anonymous
Not applicable

I am not sure if "IsVisibleInUI" parameter is relevant to my query as I just want to get all elements represented at the project Browser under the user interface "Families" tree. this is not relevant to view filters.

 

Apologies I didn't explain very well what I meant with the colours. Instead of selecting one by one the BuiltIn Categories, when possible you can select them by filtering the Family class or a super class when possible.

 

At the image of my previous post (Project Browser):

Red Elements could be filtered by using an Element Class Filter and filtering the Autodesk.Revit.DB.Family class:

 

new FilteredElementCollector(doc).WherePasses(ElementClassFilter(typeof(Autodesk.Revit.DB.Architecture.Family)))

 

 

Blue Elements could be filtered by using multiple ElementType classes

 

new FilteredElementCollector(doc).WherePasses(ElementClassFilter(typeof(Autodesk.Revit.DB.Architecture.HostObjAttributes)))
new FilteredElementCollector(doc).WherePasses(ElementClassFilter(typeof(Autodesk.Revit.DB.Architecture.FlexPipeType)))

 

 

Yellow Elements are Elements with not relevant type class such as Structural Framing. Those could be filtered by an "Of Category" Method:

 

new FilteredElementCollector(doc).OfCategory(BuiltInCateogry.OST_StructuralFraming)

 

 

Purple Elements could be represented by just an Enumeration

 

TilePatternsBuiltIn.Arrows

 

 

I hope this now makes more sense.

0 Likes
Message 9 of 9

RPTHOMAS108
Mentor
Mentor

I posted the extract from RevitAPI.chm to confirm it was not relevant to the task, sorry for the misunderstanding there.

 

Regarding your filtering strategy I think it is not necessary to do it that way.

If you filter initially for ElementType then you'll get all of those items. Then you can identify from those objects the exact derived class of ElementType. If the object remains as ElementType or turns out to be FamilySymbol then you can put those items through the further category filter.

 

However you'll find that ElementClassFilter cannot be used for all classes (some that don't exist in the native object model can't be found), this is noted in the RevitAPI.chm for ElementClassFilter. You could use ElementCategoryFilter with .WhereElementIsElementType on the collector to find and distinguish all ElementTypes.

 

This above was not my approach, I found a reasonable starting approximation by:

  1. Using ElementClassFilter(GetType(ElementType))
  2. Removing items from (1) where the Category was null
  3. Grouping remaining items from (2) into category. Unless Category.CategoryType was annotation (for those I made a branch called Annotation Symbols and put them in that).
  4. For the grouped items in (3) I further divided by their class property ElementType.FamilyName.
  5. Then finally I grouped by ElementType.Name.
  6. You then have to identify the items that shouldn't be there (this is probably easier than trying to combine things from various different filters).

If you are going to combine filters then use a LogicalOrFilter, so you keep the processing on the Revit side rather than with .Union on the API side. The union extension method needs to compare all items in the collection against each item you add to it (multiple iterations over a collection of increasing size). This is not going to be as quick as asking Revit to iterate items in the DB collection once to extract items matching an 'or' filter condition.

 

As previously noted there are no enum objects in the project browser and although the header is 'Families' they are not families. The objects under 'Families' in the project browser are all derived from ElementType. You can see for yourself by selecting an item in Pattern and then reviewing it in RevitLookup (Snoop current selection).

 

201009.PNG

You'll see TilePattern class is inherited from ElementType in RevitAPI.chm. Annoyingly it's 'CategoryType' is 'Internal', so you have to include 'Internal' categories in you initial filter to find these.

 

The complicated task is about finding the items that shouldn't be there not the items that should:

201009a.PNG

 

 

0 Likes