I've got a view/view-model (let's call it the "parent") that retrieves data in its OnNavigatedTo method. This view contains several regions of its own - these regions' views are always the same, so they are registered during application startup
using the "regionManager.RegisterViewWithRegion(...)" syntax.
After retrieving the data and performing some calculations on it, the parent VM publishes an event aggregator message to say that the data is ready. The "child" VMs subscribe to this event from within their constructors, and it's in these event handlers
where I extract the data that gets bound to their views.
For the last 12 months this approach has been working fine, but the application has recently been dealing with some larger data sets and I'm starting to find that (intermittently) the parent VM's OnNavigatedTo completes before the child views/VMs have been
instantiated, resulting in "empty" child views (because the parent publishes the EA message before the child VMs constructors have been called, so there are no subscribers).
I had assumed Prism would do stuff like this sequentially, i.e. when navigating to the parent view/VM it would call its OnNavigatedTo
before starting navigation of the child regions? Or is some of this happening on b/g threads, meaning there is no guarantee to the order in which Prism navigation does stuff?
If this is the case, what are my options? Could I simply get rid of the "RegisterViewWithRegion" startup code, and instead populate the child regions from within the parent VMs OnNavigatedTo, using "regionManager.RequestNavigate(...)"?
First, I would like to say that based on my understanding Navigation
is performed on each
independently. Therefore, it would not be a concrete sequential execution between
on different Regions
Then, I believe the approach you suggest would work correctly, but it does not seem to be pretty elegant.
However, another approach you could perform would be similar to the following thread's solution:
Basically, Registration and initializing of Views/ViewModels
should be implemented on
Initialization process. Then, in order to be sure that every
would be already instantiated, you could raise a InitializationComplete
at the end of Bootstrapper's run()
method, which would be the trigger for parents
the EventAggregator Message
for their child
. You may find detailed information in the above linked discussion thread.
I hope this helped,
My application doesn't use modules or MEF, so I don't think the proposed solution is relevant. Mine is a self-contained application with all views/VMs "living" in the main WPF project. I do still have an application "bootstrapper" where
I register everything with the IoC container (including the views/VMs), and in its InitializeShell() method is where I use regionManager.RegisterViewWithRegion() to register the "child" views with the corresponding regions in the "parent"
All of the views in question are singletons, so I guess another option could be to force them to instantiate in (say) InitializeShell(), ensuring that they've subscribed to the event in their constructors? Still not particularly elegant though.
Regarding your elegant concern, you could create a Registration
class which would perform the process of
Regions and Views Registration
as it would occur on an
implemtened class. This way, you would only call this class from the
to properly handle registration instead of having
Registering methods directly on InitializeShell()
However, an elegant design solution with Bootstrapper
would correlate the use of at least one
in order to separate the core Project
with the concrete implementation and logic of
. You may see some examples of
solution on the
Commanding and UI Composition QuickStarts
Find more information about Modular Applications
in the following
MSDN Prism Guide
I hope this helped you,