New interfaces have been added to the API to permit iteration of elements and element ids. These new interfaces have been designed to provide a more flexible and usable interface for a variety of applications, while being completely implemented in native Revit code to provide the best possible performance.

Existing element iteration routines have been replaced, including:

  • Document.Elements (all versions of this property)
  • ElementIterator
  • Filter and all subclasses of it
  • Application.Create.Filter
  • Classes and properties related to the ParameterFilter:
  • CriteriaFilterType
  • Document.FilterTypeSupported
  • FilterCriterion
  • ParameterStorage

The new element iteration interfaces offer several enhanced capabilities from their predecessors:

  • The ability to iterate and filter elements from a document, or only elements from an arbitrary list of element ids, or elements visible in a view (replacing View.Elements)
  • The ability to clearly identify filters which are designed for best performance (“Quick Filters”), which do not expand the element in memory when evaluating whether the element passes the filter
  • The ability to use chained shortcuts which automatically apply commonly used filters, e.g.

FilteredElementCollector collector = new FilteredElementCollector(document);
// Finds all walls in a certain design option
ICollection<ElementId> walls = collector.OfClass(typeof(Wall))
                                        .ContainedInDesignOption(myDesignOptionId)
                                        .ToElementIds();
 

  • The ability to logically group more than two filters.
  • The ability to match derived types automatically when using the type filter and type filter shortcut.
  • The ability to iterate elements from all design options or from any specific design option.
  • The ability to use foreach on the collector element, and to use the class with LINQ queries. This is due to the connection between the collector class and System.Collections.Generic.IEnumerable<Element>. Note that because the ElementFilters and the shortcut methods offered by this class process elements in native code before their managed wrappers are generated, better performance will be obtained by using as many native filters as possible on the collector before attempting to process the results using LINQ queries.

FilteredElementCollector collector = new FilteredElementCollector(m_doc);
// First apply a built-in filter to minimize the number of elements processed by LINQ
collector.WherePasses(new ElementCategoryFilter(BuiltInCategory.OST_Levels));

var levelElements = from element in collector
                    where element.Name == “Level 1″
                    select element;  // LINQ query to find level with name == “Level 1″

Level level1 = levelElements.Cast<Level>().ElementAt<Level>(0);

Detailed information on the new element iteration interfaces can be found in the document “Element iteration APIs” in the SDK.

Note that there are a few behavioral changes in the new iteration mechanism when compared to the old:

  • View templates were previously returned as Element. They are now returned as the correct View subclass (ViewPlan, View3d, etc). You can identify these using the new View.IsTemplate property.
  • Previous element iteration methods only returned elements of the main model, the active design option, and primary design options of each option set. Elements of design options which were not active and not primary were excluded. In the new iteration API, by default, design option membership is no longer considered when iterating elements. In order to find the same elements which were iterated in the 2010 API, you should use the following filters combined using ‘OR’:
  • An ElementDesignOptionFilter with id = InvalidElementId, to match all elements not associated to a design option.
  • An ElementDesignOptionFilter with id = DesignOption.GetActiveDesignOptionId(), to match elements in the active design option.
  • A PrimaryDesignOptionMemberFilter, to match all elements in primary design options.