views:

2092

answers:

3

I am new to Prism and I am trying to determine a best practice for deactivating a view in a Prism 2 application -- when a user clicks a button on the view I want to deactivate the view. The view is executing a command when the button is clicked.

The view model is receiving the command but the viewmodel does not have a reference to the regionmanager.

Should the view model know about the region manager? And even if the viewmodel had a reference to it, it needs the view instance to pass to the deactive method on the containing region.

I am using the MVVM pattern for the app.

any advice would be great Michael

+4  A: 

I'm gonna go on a limb here and assume that you are using an itemscontrol or such for your region, because that's the most obvious use of a "button that removes a view".

In that case, you should have a Controller (or whatever you want to call it, but the Prism team seems to use that kind of name for that kind of responsibility) somewhere in charge of managing the active ViewModels, and either you display your views using DataTemplates, or you manually create/add/activate a new view when adding a new instance. Your case seems to be the second one, and the controller should be responsible for managing the views. Your viewmodel should get a reference to that controller through Dependency Injection and ask it to remove it from the pool of active models/views.

The Controller itself receives the IRegionManager and finds the Region it is responsible for.

I hope that makes sense, please comment if it does not.

Denis Troller
It is a welcome screen that when the user clicks the button - I want it disappear revealing them main app view. The region I am using is just a contentcontrol. Does it make sense to use the IModule the view is part of as the Controller - seeing that is the one that registers the views?
MIantosca
In that case, I'd say yes.Your viewmodel could use the EventAggregator (does that exist in Prism SL ?) to signal to whatever object is responsible that it needs to discard the view. That way, your view/viewmodel stays nicely isolated from the actual job of managing regions.
Denis Troller
cool - I had thought about using an event to decouple the viewmodel from the regionmanager - maybe create a general purpose event that can be fired by any view when it needs to become deactivated. How can the view model can get a reference to the view so it can be passed along?
MIantosca
A: 

I got hung up here too. I found that because the RegionManager was responsible for the Regions it contained I was ending up with tight coupling between my RegionManager and the Regions I wanted to manage.

It was a complex job to manage these regions externally (from say a main application menu) and as a result we dropped the PRISM framework and wrote our own code based on the Composite Application Guidance elements that were of use in our particular scenario.

Mark

Mark Cooper
Did you drop all of Prism or just the Region stuff?
Cameron MacFarland
We dropped the PRISM framework components and just used the guidance (documentation) to create an eventing subsystem (works the same as the event aggregator). We are planning to re-add the PRISM framework once it has matured a little more, and wider support is available.
Mark Cooper
A: 

EventAggregator in your case (control which needs to unload itself) is maybe an overkill because simple injecting of IRegionManager to that control view model constructor

ctor (IRegionManager regionManager) { this.RegionManager = regionManager }

and then something like this

this.regionManager.Regions[regionName].Remove(this.View);

should do the thing you asked for.

IRegionManager is mockable interface enabling easy testing and it is just an abstraction not coupling you to implementation and enabling IoC

Nikola Malovic
I didn't want my views to know anything about (have dependency on)regions or region manager
MIantosca
You don't add this code in view, you add it to view model (presentation model) which IMHO is ok to get a IRegionManager. But if you want to keep the 'pure' approach, Jeremy's Screen Activator might be the way to go http://codebetter.com/blogs/jeremy.miller/archive/2009/09/07/screen-activator-pattern.aspx
Nikola Malovic