Loading controls only when needed; achieve better startup performance

Topics: Bootstrappers & IoC, UI Architecture
Aug 13, 2011 at 12:11 PM


I think I understood something really wrong!
I have a Model like this:
   - ReportItem
       - ReportSubItem
  - ReportSubItem
   - ReportItem
       - ReportSubItem
  - ReportSubItem
       - ReportSubItem
  - ReportSubItem
   - ReportItem
       - ReportSubItem
  - ReportSubItem

In words:
A collection of reports. A Report can have a collection of ReportItems, a ReportItem can have a collection of ReportSubItems

Now to the UI:
I want to display all the reports in a TabControl.
The content of one TabControlItem is a (Tile-)view, where one can see all the ReportItems belonging to the currently selected Report.
The content of one Tile is another (Tile-)view where one can see all the ReportSubItems. A ReportSubItem is a complex control (including a chart).

When I use an approach similar to the "Simple MDI Sample":
I call ActivateItem(ReportViewModel) for all the reports.
In each Report, ActivateItem(ReportItemViewModel) for all the ReportItems is called
An finally ActivateItem(ReportItemSubItem) is called for all ReportSubItems.

As this is done synchronously and as the controls are fairly complex, the applications startup behavior is really bad.
(Doesn't have to do anything with loading the data. Even with no data it is very bad)
All the controls are loaded, although only the active tabItem should be loaded.
So, of course this is really bad design, but how is it done correctly using Caliburn Micro???

Hope I could make myself clear. If not, I can refine! :)
I guess I missed something really big - but what? Please tell me!
Thanks for any kind of information concerning this topic. Thanks a lot!

All the best and greetings,

Aug 13, 2011 at 1:33 PM
Edited Aug 13, 2011 at 1:34 PM

You might investigate if it is possible to delay the actual loading of each report's subitems in the Report.OnInitialize method (which is only called at first activation).
I don't expect this to improve performance dramatically, though, unless you are dealing with a *very* large number of subitems (or with classes loaded from multiple assemblies).
I would rather check if ReportItems and SubItems are presented in a control not using virtualization: this would cause the creation of an excessive (and time consuming) number of UI items, __even for a single Report tab__.
You can quickly check it temporary removing the binding of the ReportItem/SubItem stuff. What list control are you using in ReportView? Could you post a snippet of its binding?

Aug 18, 2011 at 9:19 AM

thanks for your fast reply and sorry for my late reply!
I am not using virtualization, OnInitialize didn't help but I solved it in not using caliburn in this speciall scenario.
I am using plain old databinding now; that way, all my tabs are visible but the content of them will not be created until I finally select one!
Using ActivateItem created every tab, one after the other - that was really bad! :)

Thanks again!
All the best,

Mar 19, 2012 at 3:02 PM

See LazyScreen and LazyConductor here http://coproject.codeplex.com/

It should help you but I am afraid you would have to use ItemsControl+ContentControl instead of TabControl as described in Coproject.