1
votes

I am developing a composite WPF application using PRISM. I have a window which has a parent UserControl. This parent usercontrol has many child Regions defined. child views exports themselves using MEF's "REGIONEXPORT" attribute. Each child view imports/creates its own viewmodel. The parent usercontrol has "OK" and "Cancel" button. On pressing "OK" i want to validate and save all childviewmodels. If any validation fails then the parent usercontrol's viewmodel needs to know. To achieve this I am using a composite command and setting it in RegionContext. Each child viewmodel gets that composite command through region context and Hope you understand that basically i need to share data between parent and child viewmodels. So I need to get the RegionContext in the child viewmodel for that I am importing the RegionManager in the viewmodel's constructor (using importing construtor,) from RegionManager i get the region context and then the commands.

public class FooViewModel
{
     [ImportingConstructor]
     public FooViewModel(IRegionManager regionManager)
     {
        var regionContext = regionManager.RegionContext;
     }
}
  1. Is it a good practive to have region manager in viewmodel??
  2. Doesn't this break MVVM? we have view related stuff's in viewmodels
  3. Is there any better approach to share data between viewmodels (other than event aggregators)
1

1 Answers

2
votes

Getting a reference to the Region Manager via the constructor of a view model is not unusual. It is the preferred method to get it. I do it this way all the time when I need to use the Region Manager for navigation.

This approach does not break MVVM. Although, I am not sure what you plan on doing with the RegionContext itself.

Another way to pass data from one VM to another is via NavigationParameters and the Region Managers RequestNavigate function. An example is below.

private readonly IRegionManager _regionManager;

public YourViewModel(IRegionManager regionManager)
{
    _regionManager = regionManager;
}

Private void DoNavigation()
{
    var parameters = new NavigationParameters();
    parameters.Add("Key", <a value or an object to pass>);
    _regionManager.RequestNavigate(“ContentRegion”, “YourViewName”, parameters);
}

You can check the parameters collection for values in the OnNavigatedTo method of the receiving VM.

public override void OnNavigatedTo(NavigationContext navigationContext)
{
    var paramKey = navigationContext.Parameters.Where(item => item.Key == "Key").FirstOrDefault();

    if (paramKey.Value != null)
    {
        // Do something…
    }    
}

You need to implement INavigationAware to get OnNavigatedTo to work.

EDIT:

If you want your data sharing to be more loosely coupled that talking to another view model via the Region Context, and you don’t want to use the Event Aggregator, then a shared service may be another way to go.

With a share service, some or all of the view models can have a reference to it, and when a property changes in the service, any object that has a reference to it can act. This share service can implement the BindableBase that comes with Prism and therefore notify when changes occur. Register the share service with whatever container you are using, get it in the ctor of the view model, reference the properties as is appropriate.

Shared Service Example