Best practice to creating a new view and registering with a region

Topics: Prism v4 - Silverlight 4
Feb 16, 2012 at 8:05 PM

Hey there, I'm having issues understanding how I should be creating a new view and registering it with a region.

I'm using MEF and the quickstart Shell from David Hill's templates. I have one module which is supposed to beable to create and display data for my PasswordPolicies Table, ValidationGroups Table and ValidationRules Table. ValidationGroup is the junction for the other two tables, basically many Rules can be used in a Policy and many Policies can use the same rules.

My views:
ShellView - Holds a region [MainRegion]
PoliciesView - Shows the rows within the Policy Table, has a "Add New Policy" button that should navigate the [MainRegion] view to AddNewPolicyView
AddNewPolicyView - Creates a new row, contains a region [ValidationGroupRegion] (I also want to share the Policy model over to the ValidationGroupView through RegionContext)
ValidationGroupView - Shows the associated Rules from a given Policy
ValidationRulesView - Shows the rows within the Rule Table

I assume from the diagram associated with the RegionContext that the RegionContext is what I want to use for sharing the Policy Model, if not then what should I be using?
I have ViewDiscovery on my Module INIT to assign PoliciesView to Region[MainRegion].


What I'm wondering is whats the normal way of creating a new View and putting it into the region? I've tried simply adding the View to the region but then my ViewModel property within the View's Codebehind is null because the [Import] doesn't seem to fire.

regionManager.Regions[MainRegion].Add(new AddNewPolicyView());

Feb 16, 2012 at 9:10 PM
Edited Feb 16, 2012 at 9:19 PM

Well I figured out that I could use ServiceLocator to get an instance of the View (and since its Non-Shared, it'll create a new one) and after Submitting I'll have to figure out how to tell it to remove itself (part life time I'm guessing and tell it not to keep it alive).

_regionManager.RegisterViewWithRegion(RegionNames.MainRegion, () => ServiceLocator.Current.GetInstance<AddNewPolicyView>());

But now I run into an issue with my RegionContext. I can't just register my ValidationGroupView with my AddNewPolicyView's region [ValidationGroupRegion] in the [ImportConstructor] because the region hasn't been created on the view yet, and thus not in the RegionManager.


public AddNewPolicyViewModel(IRegionManager regionManager)
    _regionManager = regionManager;
    _regionManager.RegisterViewWithRegion(RegionNames.ValidationGroupsRegion, () => ServiceLocator.Current.GetInstance<ValidationGroupView>());

Then the [ImportingConstructor] gets called on the ValidationGroupViewModel

public ValidationGroupViewModel(IRegionManager regionManager)
    _regionManager = regionManager;
    var RegionContext = _regionManager.Regions[RegionNames.ValidationGroupsRegion].Context as PasswordPoliciesModel;
    this.Policy = RegionContext as PasswordPoliciesModel;

And within the Regions I only have [MainRegion] not my [ValidationGroupsRegion] since the AddNewPolicyView hasn't finished.

I assume there has to be a way todo this and I'm just missing it.


Xaml code for ContentControl on AddNewPolicyView

    prism:RegionManager.RegionContext="{Binding Path=Policy, Mode=TwoWay}"

Further testing I discovered if I have a button to Register the View with the Region then everything works like I want it to, but then I have to keep track of the fact that I've registered the view.

Feb 22, 2012 at 8:24 PM


Based on my understanding, the problem seems to be that you are trying to retrieve the context of a region in the view model before the construction of its view is finished. As the region is not available until the view is properly created, the region does not exist during the construction of the view model.

As a possible approach you could subscribe to the CollectionChanged event of the Regions collection of the RegionManager in the view model's constructor. When the ValidationGroupsRegion is added to the RegionManager this event will be fired and you should be able to retrieve the context of the region. For example, you could do something something similar to this:

public ValidationGroupViewModel(IRegionManager regionManager)
    _regionManager = regionManager;
    _regionManager.Regions.CollectionChanged += Regions_CollectionChanged;

void Regions_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    if (_regionManager.Regions.ContainsRegionWithName(RegionNames.ValidationGroupsRegion))
        _regionManager.Regions.CollectionChanged -= Regions_CollectionChanged;
        var RegionContext = _regionManager.Regions[RegionNames.ValidationGroupsRegion].Context;
        this.Policy = RegionContext as PasswordPoliciesModel;

However, take into account that the decision of which approach you should use will depend mostly of your personal preferences and the requirements of your scenario.

You can find more information about the RegionContext in the following section of the Prism documentation:

I hope you find this useful,

Damian Cherubini

Feb 24, 2012 at 4:33 PM

Thank you very much! Still forgetting I can do the whole Async callbacks. I'm currently using a button but the above approach is much cleaner for what I want todo.