Dear Bernie,
Thank you for your query, and many thanks to Recep for his very helpful answers.
I have a suggestion based on a slightly more abstract view of the task which may help implement a more optimised solution for both this and other purging tasks.
By the way, looking back at your original question: What is `f`, that you call `Refresh` on? I guess that does not matter?
I believe this can indeed be easily solved.
The trick is to find some characteristic feature to test on the ViewSection class that let us determine whether it is referenced or not, or how many references to it exist.
What is a reference to a section view, and where can it be determined?
Is it always a reference from a sheet view?
Can it always be determined by calling the ViewSheet GetAllPlacedViews method?
http://www.revitapidocs.com/2020/af2ee879-173d-df3a-9793-8d5750a17b49.htm
If so, then here is my suggestion:
The Revit API GetAllPlacedViews method defines a relationship mapping a ViewSheet to all views placed on it, including ViewSection objects.
This relationship can easily be inverted to map the ViewSection objects (or all placed views) to all ViewSheet objects referencing it.
I discussed a simple relationship inverter in one of the first blog posts, number 16, in 2008:
http://thebuildingcoder.typepad.com/blog/2008/10/relationship-in.html
It is maintained as part of The Building Coder samples, in the module CmdRelationshipInverter.cs.
Later, in 2009, The Building Coder also discussed the relationship between viewports and sheets:
http://thebuildingcoder.typepad.com/blog/2009/01/viewports-and-sheets.html
The discussion there and the command that it implements is too convoluted and gets into too much detail for me to understand fully right here and now. I am either too lazy, busy or obtuse. So, instead, I'll start again from scratch.
Implement map_sheet_to_placed_views like this:
- Dictionary<int, List<int>> map_sheet_to_placed_views
- For each sheet, call GetAllPlacedViews
- Add the integer values of the sheet and placed views element ids as key and value
To invert the relationship:
- Dictionary<int, List<int>> map_placed_view_to_sheets
- Iterate over all the placed sheet entries in the values in map_sheet_to_placed_views
- For each placed sheet, add its element id integer value as key to map_placed_view_to_sheets if it does not already exist, and the associated sheet int key to the associated list of int value
With that reverse relationship set up, you know that every placed view has an entry in map_placed_view_to_sheets pointing to the sheets it has been placed on.
An unplaced view has no such entry.
Therefore, you can simply add a post-processing step to the filtered element collector above to eliminate the placed views from the filter results and retain only unplaced views:
var secIds = new FilteredElementCollector(doc)
.OfClass(typeof(ViewSection))
.ToElementIds()
.Where<ElementId>( id =>
!map_placed_view_to_sheets.ContainsKey(id.IntegerValue) );
One big advantage of this approach is that you know exactly what you are doing, and that each step is performant:
- One single filtered element collector call to retrieve all the sheets and create map_sheet_to_placed_views
- The relationship inversion, a pretty fast operation
- One single filtered element collector call to retrieve all section views
I hope this helps.
Best regards,
Jeremy