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.
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.
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.
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.
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 believe the root cause of this issue is an implementation issue of TransitioningContentControl.
This control (which has many existing implementations all over the place, most of which originated from Silverlight one AFAICT) will cause an extra load/unload transition when navigating out of a content.
The current control will trigger Unload/Load/Unload when navigating out, instead of single Unload. This issue is referenced in many places.
When used in RxUI, this bug causes WhenActivated
to be called on the leaving View, causing performance issues, especially if the current view is complex.
TransitioningContentControl should be re-written to avoid this extra transition, here's an sample implementation which doesn't suffer from this issue.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With