Search code examples
mvvmprismcompositemvp

In Prism (CAL), how can I RegisterPresenterWithRegion instead of RegisterViewWithRegion


I have a module in a Prism application and in its initialize method I want to register a presenter instead of a view with a region, i.e. I want to do this:

PSEUDO-CODE:

regionManager.RegisterPresenterWithRegion(
        "MainRegion", typeof(Presenters.EditCustomerPresenter));

instead of loading a view like this:

regionManager.RegisterViewWithRegion(
        "MainRegion", typeof(Views.EditCustomerView));

The presenter would of course bring along its own view and ultimately register this view in the region, but it would allow me to bind the presenter to the view in the presenter's constructor instead of binding the two together in XAML (which is more of a decoupled MVVM pattern which I want to avoid here).

How can I add a Presenter to a Region instead of a view?

namespace Client.Modules.CustomerModule
{
    [Module(ModuleName = "CustomerModule")]
    public class CustomerModule : IModule
    {
        private readonly IRegionManager regionManager;

        public CustomerModule(IRegionManager regionManager)
        {
            this.regionManager = regionManager;
        }


        public void Initialize()
        {
            regionManager.RegisterViewWithRegion("MainRegion", typeof(Views.EditCustomerView));
        }
    }
}

Solution

  • I think your presenters should be responsible for inserting them into the region when they are activated. I usually create an IViewRegistry for my presenters to use that avoids them knowing about region names and have their presenters use this to show the view.

    public class MyViewPresenter : IPresenter
    {
         IViewRegistry _viewReg;
         IUnityContainer _container;
         public MyViewPresenter(IViewRegistry viewRegistry, IUnityContainer container)
         {
              _viewReg = viewRegistry;
              _container = container;
         }
    
         void IPresenter.Present()
         {
              MyView view = _container.Resolve<MyView>();
              MyViewViewModel vm = _container.Resolve<MyViewViewModel>();
              view.DataContext = vm;
    
              _viewReg.ShowInMainRegion(view);
         }
    
    }
    

    And then of course, the implementation of ShowInMainRegion would be that region registry code you already have.

    public void ShowInMainRegion(object view)
    {
         regionManager.RegisterViewWithRegion(
            "MainRegion", view);
    }
    

    There is a possibility you could do something that is more like what you want (a region adapter that detects an IViewFactory, maybe), but it's probably not practical.

    Hope this helps, Anderson