views:

547

answers:

4

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));
        }
    }
}
+1  A: 

I'm still quite new to Prism but as I understand it, that doesn't make sense: Regions are designed to hold Views, aren't they. That's all they exist for. What are you hoping to get from your Region that your Presenter can use?

Given that your Presenter knows all about your View, can you use your Presenter in your RegisterViewWithRegion call:

regionManager.RegisterViewWithRegion(
    "MainRegion", typeof(Presenters.EditCustomerPresenter.View));
serialhobbyist
+2  A: 

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

Anderson Imes
+1  A: 

You can try using the RegisterViewWithRegion overload that takes a delegate instead of a view type.

For example:

regionManager.RegisterViewWithRegion(RegionNames.APPLICATION_MANAGEMENT_REGION, OnGetManagementView);

public object OnGetManagementView()
{
     return m_managementViewModel.View;
}

This will allow you to have your own custom logic for creating the view/viewmodel(aka presenter). The callback will be called when the named region is found.

Jeremiah Morrill
A: 

My approach to this is to register the view with the region by passing it the View property of a resolved presenter

this.regionManager.RegisterViewWithRegion(
    FoundationToolkitRegionNames.RIBBON_REGION, 
    () => this.container.Resolve<SetupRibbonTabPresenter>().View);

My presenters constructor would look like this:

public SetupRibbonTabPresenter(ISetupRibbonTabView view)
{
    this.view = view;
}

Both the view and presenter have previously been registered in the container.

Johan Badenhorst

related questions