I've been studying the pyRevit code for purging viewports, and it's intriguing how the developer approached the task. It seems their aim was to gather a collection of all viewport types from the document. However, identifying viewport types directly posed a challenge because they lack a defined category or specific class. Instead, they are categorized under the ElementType class, which serves as a base class for all element types in Revit.
To overcome this obstacle, pyRevit implemented a try-catch mechanism. By attempting to switch a viewport instance type to another type, they could determine if it belonged to the category of viewport types. Once pyRevit collected these types, it filtered out the viewport instance type IDs from the potentially purgable IDs and proceeded to delete them.
Considering alternative approaches, one could explore the possibility of identifying purgable viewports indirectly by targeting existing parameters. For example, since ViewportType is a system family and all must possess the "Show Extension Line" parameter (BuiltInParameter.VIEWPORT_ATTR_SHOW_EXTENSION_LINE), we can use this parameter as a filter rule to identify all types that possess it. Fortunatly, this parameter is a bool parameter, which its value is either 0 or 1, then we can use (ParameterFilterRuleFactory.CreateGreaterOrEqualRule) and supply a value 0 for checking.
With a list of viewport types established, the next step involves iterating through each type to retrieve the associated viewports using the GetDependentElements(ElementFilter) method.
Here's an example to illustrate the process:
// create filterRule to be used in collection
var rule = ParameterFilterRuleFactory.CreateGreaterOrEqualRule(
new ElementId(BuiltInParameter.VIEWPORT_ATTR_SHOW_EXTENSION_LINE),0
);
// get all elements that comply to this rule
var viewPortTypes = new FilteredElementCollector(doc)
.WhereElementIsElementType()
.OfCategory(BuiltInCategory.INVALID)
.WherePasses(new ElementParameterFilter(rule));
// now for each viewportType find a viewport instance dependent
List<ElementId> purgeableIds = new List<ElementId>();
foreach (var viewportType in viewPortTypes)
{
var viewports = viewportType.GetDependentElements(
new ElementCategoryFilter(BuiltInCategory.OST_Viewports)
);
if (!viewports.Any())
{
purgeableIds.Add(viewportType.Id);
}
}
// show a list of all purgeable Ids
MessageBox.Show(
string.Join("\r\n", purgeableIds.Select(o => o.Value.ToString()))
);
// ... handle these ids
I just tested it on 2025, would be glad to know if there are some holes in this method.
Moustafa Khalil