RequestNavigate - Create view

Topics: Prism v4 - WPF 4
Sep 16, 2011 at 4:34 PM

I’m fairly new to prism, and I’m currently re-writing one of our existing applications using prism as a proof of concept project.

The application uses MVVM with a ViewModel first approach: Our ViewModel is resolved by the container, and an IViewResolver service figures out what view it should be wired up to (Using name conventions amongst other things)

The code (to add a view to a tab control) at the moment looks something like this:

var vm = (..get ViewModel from somewhere)
IRegion reg = _regionManager.Regions["MainRegion"];
var vw = _viewResolver.FromViewModel(vm); // Spins up a view and sets its DataContext
reg.Add(vw);
reg.Activate(vw);


..which all works fine, however I’d really like to use the Prism navigation framework to do all this stuff for me, so I could do something like:

_regionManager.RequestNavigate(“MainRegion”, new Uri(“NameOfMyViewModel”, UriKind.Relative));

and have Prism spin up the view model + view, set the DataContext and Inject the view. I’ve had some success by creating DataTemplates referencing the ViewModel types

ie:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Module01">
<DataTemplate DataType="{x:Type local:TestViewModel}">
<local:TestView />
</DataTemplate>
</ResourceDictionary>

...and have the module add the relevant resource dictionary into the applications resources when the module is initialized, but that seems a bit rubbish.

Is there a way to effectively take over view creation from Prism, so that when a view is requested I can supply one? There’s an overload of RegionManager.RegisterViewWithRegion that takes a delegate that allows you to supply a view yourself, and I guess I’m after something like that.

I think I might need to supply my own IRegionBehaviorFactory, but unsure what’s involved (or even if I’m on the right path!)

Any help appreciated!

Developer
Sep 16, 2011 at 7:16 PM
Edited Sep 16, 2011 at 7:17 PM

Hi,

As far as I know, a common possibility to support the view model first approach is using DataTemplates. A DataTemplate allows you to "pair" a view model with a view and still keep them decoupled. This can be done because neither of them know each other; they are only related through a DataTemplate defined in the module.

In the approach that you suggest, the "view resolver" would need to know which view model correspond to each view, therefore, the views and view models would not be completely decoupled. If you wish, you could implement an extension method that accepts a delegate with a view model as a parameter. Internally, that extension method could obtain the corresponding view for the view model, set the data context of the view and then, invoke a common method using that view as a parameter. However, this is not a usual approach when using the view model first approach.

For more information about the view model first approach you might find the following links useful:

I hope you find this useful,

Damian Cherubini
http://blogs.southworks.net/dcherubini

Sep 16, 2011 at 9:24 PM

 

Thanks for the reply - I can kinda get it working using data templates, but if the DataTemplate is defined in a module (which it almost always will be) then I’d have to have something in the Apps resource file referencing that modules resource dictionary (creating a dependency between the application and the modules it’s hosting) which isn’t ideal.

The view locator service doesn’t introduce any coupling between our viewmodels and their views - most of it happens using either naming conventions (ie, given a viewmodel of type ‘TestViewModel’ it’ll try to find a ‘TestView’ type from a series of registered locations, starting with the container)

Presumably (and I’m new to Prism so forgive me if I’m wrong!) when you do something like .RequestNavigate() passing a Uri, something takes that Uri and spins up a view based on that (using the name it was registered with the container by the look of it)

Is there no way to override that bit of functionality?
Sep 19, 2011 at 3:41 PM

For anyone else looking for this sort of functionality, IRegionNavigationContentLoader is the way to go. See here

Developer
Sep 19, 2011 at 5:16 PM

Hi,

Thanks for sharing this with the rest of the community, as it might be useful for other users pursuing this scenario.

Regards,

Agustin Adami
http://blogs.southworks.net/aadami