In my WPF
application which makes use of ReactiveUI
, I've noticed an area of poor performance.
I have a view-model which contains a lot of other lightweight view-models (think 30ish). These nested view-models are simple, usually representing a button each. They're all displayed within a user control, inside an ItemsControl
which is wired using ReactiveUI's OneWayBind
. This means that each item is displayed using ViewModelViewHost.
So, the problem
On my powerful desktop PC, when I navigate to this view-model, there is a noticable delay between pressing the "go-to-view-model" button and the view changing, around 0.5 seconds. When I run the same software on a Power-PC, the delay is nearly 4 seconds. This is a pretty big issue from an UX point of view.
What I've learned
I tried profiling and debugging my code for a long time, and found no problem areas. Zilch (note: using JustMyCode in VS so ReactiveUI didn't show up). I did however, find a way to remove the issue. Instead of binding to the ItemsControl.ItemSource
with OneWayBind
, I did so in XAML, as such:ItemSource={Binding MyViewModels}
and setting the DataTemplate
manually. This results in a much quicker transition.
When you bind with OneWayBind
with an ItemsControl
, a ViewModelViewHost
is automatically created for you, and the ViewLocator
is used to find the view for your view-model. I'm assuming this is very slow for some reason.
Question
Is anyone aware of how I can get around this performance hit without having to manually define lots and lots of data-templates for an ItemsControl? If I have view-models of view-models of view-models, then things tend to get ugly very quickly. From my past experiences with Caliburn.Micro
, the view-location conventions were very quick, so I'm also wondering if I'm not quite using ReactiveUI
properly, and that there is an alternative approach which is quicker.
Thank you.
TLDR;
ViewModelViewHost
as a DataTemplate
for ~30 view-models causes views to be very sluggish when initially loaded, leaving the UI to look as if it has crashed. Is there any way to avoid this?
I've run into this exact same problem before.
Essentially, you want to show/hide, rather than create/destroy.
Creating a new visual tree is lots of work, and you will typically get delays of seconds or more when you switch tabs.
Now if you create everything, then collapse what you dont need and show it on demand, suddenly everything updates in an eyeblink.
It may take a bit of refactoring to do this, and the code may not look as clean, but it sure as hell runs blazingly fast.