wpfregionprism-7composite-applicationregion-management

Working with nested views using Prism with IsNavigationTarget which can return false


I'm trying to find solution for the following problem. I have a WPF app, I used mvvm and prism (most recent version 7) to build it. Here is the draft of the form/dialog I work on: User dialog structure

MainView has region - region1, I inject SubViewA into region1 based on what is selected in treeview. This view represents treeitem content. SubViewA itslef has region - region2, and another view - SubViewB is injected into region2 based on combobox selection.

I use INavigationAware to manage injection to the region.

So to inject view into region I use from MainViewModel the following:

_regionManager.RequestNavigate(regionName, viewName, callBack, parameters);

In the SubViewAViewModel I implement INavigationAware, and to reuse created views I check if view per treeitem was created. To do it I add into parameters a treeitemId and then I check this id in IsNavigationTarget method like this:

bool IsNavigationTarget(NavigationContext navigationContext)
{
    // get id parameter from navigationContext.Parameters
    // check if subviewA for treeitemId was already shown and return true,
    // i use dictionary, where i store ids of all items that were selected in the past
    // otherwise return false.
}

The same method I use when I want to inject SubViewB into region 2 of SubViewA. Mostly when user changes dropdown selection new SubViewB is injected.

Now my question is - if I use INavigationAware in SubViewBViewModel and when IsNavigationTarget always returns true - all is good. When I try to reuse views and again chose what to return true or false, then when I select second item in treeview I got an exception: "Region with the given name is already registered" - prism complains that region2 was already registered.

I know that I can have service and always populate data from the service when View is shown, and because of that I don't need to reuse views. But it's more academic question - what is the proper way to solve it?

P.S. I tried to register scoped region manager, but I was not successful, my problem is I don't know where is the best place to create new scoped manager and how to inject it into viewmodel. Parent's ViewModel is not good place to do it, because I have to expose view. If I try to use attached behavior, then it seems, region content is updated before behavior is invoked.

P.S.2 I found an example from pluralsight (by Brian Lagunas), where he creates two shells, but it differs from what I want to achieve. He creates new scope manager per window in the moment when window is created. And also if window itself will have the same structure as I showed above, it will fail too.

P.S.3 I watched recent streams from Brian Lagunas where he is writing outlook from scratch, his approach is based on behavior, he associates some view with dependent views, it works fine, but again in his example dependent views don't contain regions.

Thank you.


Solution

  • For those who are interested in details, you have to watch the following pluralsight courses: pluralsight.pxf.io/XVxR5 & pluralsight.pxf.io/B6X99. One is about multiple shells and another is about tabbed control, which is called 'Prism Problems & Solutions: Mastering TabControl' - this course helped me.

    In short, the problem is about how to inject scope region in the main viewmodel. To solve it we have override ScopedRegionNavigationContentLoader plus to control either we want to inject scoped region manager or global one we have to us marking interfaces.

    I created another question which is similar to current one: please check Prism 7 throws and exception when working with nested views. It will give you more details.