As usual, I have been much too active in the Revit API discussion forum recently and worked too little for my taste here in the blog.
Here are some of the recent items that I want to share plus a few pictures from my latest mountain outing:
Here is a picture from a little ski tour to Balmer's Graetli in Muotathal last Sunday, sporting a nice new warm fur hat with ear flaps, aka shapka ushanka, that my ex-Autodesk-colleague Marat got me:
You can see more photos from the tour in my Balmer's Graetli album.
Many thanks to Marat for the hat and to Conny for the nice destination!
More and longer ski tours are planned for the end of March and April.
Congratulations to my Indian Colleague Naveen Kumar T. for reaching place two in the list of top solution authors!
I am really looking forward to the day he overtakes me!
Thank you ever so much, Naveen, for all the hard work and great success!
Another discussion forum related news item:
For your information, Patrick Emin recently pointed out the new French language Revit and BIM discussion forum in the thread on using a form in Revit API:
Bonjour, pour votre information, nous avons un forum en français: Revit et BIM – Français – forums.autodesk.com/t5/revit-et-bim-francais/bd-p/198
Bienvenue sur les forums Revit d’Autodesk. Partagez vos connaissances, posez des questions, collaborez sur des idées, et explorez les sujets Revit populaires.
Let's return to a more technical Revit API oriented topic in the thread on a WPF window with treeview and slow load with virtualization:
Question:
A tool I'm building has a TreeView control that will show all element instances in a Project/Active/Selection.
The problem is that even with UI virtualization the window load times are far too long.
I'm not sure what to suspect now and am hoping one of the community has run across this.
Some examples of window load times below.
Here is some additional pertinent information .
Screenshot #1:
Screenshot #2:
Here is TreeViewAllElementInstances.zip containing my sample code.
Answer: I would suggest initially populating only the Tier 1, and then populating the other ones and their subnodes on demand when clicked by the user to open them.
If a specific node is never opened, there is no need to ever load its subnodes.
I am sure such techniques have already been implemented and published in the past.
In fact, I see a large number of solutions when searching the Internet for populate tree view on demand.
Response: Jeremy, thank you for your suggestions and for continuing to help me and the community!
Much has happened since last Wednesday and I can report back that I now have a virtualized TreeView which quickly handles projects with 200,000+ model elements!
I will gladly share this solution with any needing it so if you're interested please contact me.
Initially, my inexperience drove me to go the 'safe' route towards populating the TreeView, but on Thursday, I deleted most of what I'd done and fully embraced MVVM and working with Objects, in an object, in an object, in an object! Was a mind melter for me but it really paid off!
The method below is truly the meat of the solution and along with the XAML in the previously attached ZIP file make it work. Way shorter and simpler than I thought it would be.
private static void InitializeDataSource() { Tier1CategoryNames = new ObservableCollection<Tier1Object>(); Tier1Object tier1Object = null; Tier2Object tier2Object = null; Tier3Object tier3Object = null; Tier4Object tier4Object = null; foreach( var revitElementInstance in _revitElementInstances ) { // ########## Tier 1 Start ########## var currentCategoryName = revitElementInstance.Category.Name; if( Tier1CategoryNames.Count == 0 || Tier1CategoryNames.All( tier1Object1 => tier1Object1.Tier1CategoryName != currentCategoryName ) ) { Tier1CategoryNames.Add( tier1Object = new Tier1Object( currentCategoryName ) ); } // ########## Tier 2 Start ########## var currentFamilyName = revitElementInstance.FamilyName; if( tier1Object.Tier2FamilyNames.Count == 0 || tier1Object.Tier2FamilyNames.All( tier2Object1 => tier2Object1.Tier2FamilyName != currentFamilyName ) ) { tier1Object.Tier2FamilyNames.Add( tier2Object = new Tier2Object( currentFamilyName ) ); } // ########## Tier 3 Start ########## var currentElementTypeName = revitElementInstance.ElementType.Name; if( tier2Object.Tier3ElementTypeNames.Count == 0 || tier2Object.Tier3ElementTypeNames.All( tier3Object1 => tier3Object1.Tier3ElementTypeName != currentElementTypeName ) ) { tier2Object.Tier3ElementTypeNames.Add( tier3Object = new Tier3Object( currentElementTypeName ) ); } // ########## Tier 4 Start ########## var currentElementInstanceName = revitElementInstance.ElementInstance.Name; tier3Object.Tier4ElementInstanceNames.Add( tier4Object = new Tier4Object( currentElementInstanceName ) ); } }
Congratulations on the brilliant result and many thanks to Chris for sharing the solution!
Unrelated to the Revit API and technology, you might be interested in Underture, a truly beautiful two-minute underwater video by LaughingEelVideo with masses of fascinating creatures filmed in Indonesia to the music of The Barber of Seville by Gioachino Rossini:
Sometimes, being underwater feels like a window on the world's biggest stage. Here's a bouncy 4K introduction to some of its principal characters, shot in Indonesia: Komodo, Ambon, Raja Ampat, and Bali.