3
votes

I am using prism view-based navigation with the RequestNavigate method.

The problem I encouner is that I have to register all the ViewModels with the container:

container.RegisterType<object, InboxView>("InboxView");

This is very verbose and requires a list of all the view types I want to register.
Is there any workaround for it?

I think the RequestNavigate should have been generic:

IRegion.RequestNavigate<TView>();

And should perform the following:

  1. Resolve the view
  2. Give the view a name in the region that should be typeof(TView).Name
  3. Perform the actual navigation request :)
  4. Please vote for my suggestion digest in the Prism issues list.
1
Is your problem that you have to register all view models or all views? Your example isn't clear about that. Besides that, the mapping name "InboxView" as a parameter of RegisterType<T,U> is not needed. - PVitt
@PVitt, yes. that is my problem. I want these mappings to be automated, actually I am thinking of doing it by subclassing the Region and overriding or shadowing the RequestNavigate methods adding the view registeration there (an IUnityContiner will be injected to its constructor), what do you think? BTW, I've posted a suggestion to the Prism codeplex site, please review/vote it. - Shimmy Weitzhandler
@Shimmy: for concrete types, you don't have to do a RegisterType to allow the container to instantiate it. However, for some reason you are mapping all requests to instantiate an object of type "object" to your InboxView type. I'll be blunt and say that if you have to do this, you are doing something wrong. - Anderson Imes
@Shimmy post a full sample so we can take a look at it and point you in the right direction. - Anderson Imes
@Anderson Imes. Believe me that I also hate the idea of registering a view-type with object, it indeed sucks. BUT, take a look here (check out the "Important" section and a little before it), and you'll see that it's essential and unfortunatelly not wrong. - Shimmy Weitzhandler

1 Answers

0
votes

I see what you are trying to get at, but the proposed solution doesn't really meet with design goals of RegionManager. In particular:

  1. Region requests are type agnostic. If you don't have a reference to a type in Module A from Module B, but want to navigate there, how can can you navigate without these modules referencing each other or having those types refactored into a 3rd assembly?
  2. Regions can have as many views of a particular type as necessary. Your proposed solution would artificially limit the number of views of a particular type to one, which is not currently how regions work.

This doesn't answer your question, though.

As for reducing the verbosity, there isn't much you can do other than roll your own solution that encapsulates the behavior your want in front of RegionManager. Personally I wouldn't go this route, but it's certainly something you could do. You can write this as your own service, or simply an extension method on IRegionManager or IRegion.

public interface IMyNavigationService
{
     //Your own implementation could use (typeof(T)).Name (or 
     //AttributedModelServices.GetContractName(typeof(T)) if using MEF)
     //as the Key, if thatis appropriate for your solution 
     //(1 instance T per region and references to T from all Modules)
     void RequestNavigation<T>();
}

It looks like a switch to MEF as an IoC container might help for your needs... it just depends on which of these lines of code you don't care for. For me, I don't like the RegisterType<object, InboxView>. The MEF equivalent would be:

[Export]
public class InboxView { .. }

You can provide a contract name here ([Export("InboxView")]), but by default it will provide a contract name of AttributedModelServices.GetContractName(typeof(InboxView)). As long as whatever you choose is consistent with how you chose to generate the name in the implementation of IMyNavigationService, it should work fine.

Here is the same thing, but with an extension method implementation (with a MEF implementation... you can choose some other key generation method if you use Unity... you'll just have to add registration of that type in the method as well)

public static class RegionExtensions
{
    public static void RequestNavigate<T>(this IRegion region)
    {
        region.RequestNavigate(AttributedModelServices.GetContractName(typeof(T)));
    }
}

If you are nervous about switching everything to MEF, there is a MefContrib project that makes this much easier... it basically combines Unity and MEF in one.

Hopefully this helps.