Dear Chintan,
Thank you for your query.
Aaron is absolutely right.
Basically, the filtered element collector is the one and only channel to retrieve elements from the Revit database.
Before it was 'filtered', it was just an element collector and really slow. Back then, you definitely wanted to retrieve everything of interest in one single call, and then structure it yourself.
Now, you could potantially set up numerous filtered element collectors in loops to achieve the kind of hierarchical query you describe.
You could start like this:
FilteredElementCollector levels
= new FilteredElementCollector( doc )
.OfClass( typeof( Level ) );
foreach( Level level in levels )
{
// Now what?
// We could set up new filtered element
// collectors for each level, but it would
// get complex and we would start repeating
// ourselves...
}
I think it would still be better to get all elements at once, and then sort them into the structure yourself, something like this:
// Get all family instances and use those to
// set up dictionaries for all the required
// mappings in one fell sweep. In the end, we
// will need the following mappings:
// - level to all categories it hosts instances of
// - for each level and category, all families
// - family to its types
// - family type to instances
FilteredElementCollector instances
= new FilteredElementCollector( doc )
.OfClass( typeof( FamilyInstance ) );
// Top level map.
Dictionary<ElementId, // level
List<ElementId>> // categories
mapLevelToCategories = new
Dictionary<ElementId,
List<ElementId>>();
// What we really need is something like this.
// It will probably simplify things to implement
// a custom kind of dictionary for this to add
// new entries very simply.
Dictionary<ElementId, // level
Dictionary<ElementId, // category
Dictionary<ElementId, // family
Dictionary<ElementId, // type
ElementId>>>> // instance
map = new Dictionary<ElementId,
Dictionary<ElementId,
Dictionary<ElementId,
Dictionary<ElementId,
ElementId>>>>();
foreach( FamilyInstance inst in instances )
{
Category cat = inst.Category;
Level lev = doc.GetElement( inst.LevelId ) as Level;
FamilySymbol sym = inst.Symbol;
Family fam = sym.Family;
Debug.Assert( null != cat, "expected valid category" );
Debug.Assert( null != lev, "expected valid level" );
Debug.Assert( null != sym, "expected valid symbol" );
Debug.Assert( null != fam, "expected valid family" );
if( map.ContainsKey( lev.Id ) )
{
mapLevelToCategories[lev.Id].Add( cat.Id );
}
else
{
// First time we encounter this level,
// so start a new level.
List<ElementId> categoriesOnLevel
= new List<ElementId>( 1 );
categoriesOnLevel.Add( cat.Id );
mapLevelToCategories.Add( lev.Id,
categoriesOnLevel );
}
// Sort into families and types pere level and category...
}
I hope this helps.
Best regards,
Jeremy