Search code examples
c#wpfmvvmstylet

How to keep Views and ViewModels in seperate NameSpaces (, and assemblies) in Stylet


I have started using Stylet for MVVM in WPF. I have my Views in the namespace StyletProj.Pages with the Bootstrapper in the namespace StyletProj, and my ViewModels in the namespace StyletViewModels.ViewModels (in another assembly). I need to have the Views and ViewModels linked. How can I do this? This is what I have so far in my bootstrapper.

namespace StyletProj
{
    public class Bootstrapper : Bootstrapper<ShellViewModel>
    {
        protected override void ConfigureIoC(IStyletIoCBuilder builder)
        {
            // Configure the IoC container in here
        }

        protected override void Configure()
        {
            // Perform any other configuration before the application starts
            var viewManage = this.Container.Get<ViewManager>();
            viewManage.NamespaceTransformations
        }
    }
}

What do I do with NamespaceTransformations? Is this the wrong way? I also found this example (and wiki page), but they suggest to create a whole new ViewManager to do this, which seems a tad bit overkill. How do I go about this in the simplest way possible (I'd rather not create a new ViewManager? I don't even understand what they are doing in the example.


Solution

  • You do not have to create a new ViewManager, as this scenario is already supported.

    You just have to add a namespace transformation to the ViewManager that maps a view model from StyletViewModels.ViewModels namespace to a view from the StyletProj.Pages namespace.

    protected override void Configure()
    {
       var viewManager = Container.Get<ViewManager>();
       viewManager.NamespaceTransformations.Add("StyletViewModels.ViewModels", "StyletProj.Pages");
    
       // ...other configuration code.
    }
    

    You can add key-value pairs to the NamspaceTransformations dictionary. What namespace transformations do is basically replacing the prefix of a view model type name that matches a key of an entry in the dictionary with its value. In other words, it says if you pass a view model in namespace A, search for the corresponding view in namespace B.

    A side note on using the container. When you have types in other assemblies, you need to register them, so the conatiner knows them and can instantiate them. You can reference the assembly and bind the target classes manually e.g.:

    builder.Bind<MyViewModel>().ToSelf();
    

    However, it is easier to register the assembly, so the container can discover all types automatically. I assume that the sample assembly is called StyletViewModels.ViewModels:

    builder.Assemblies.Add(Assembly.Load("StyletViewModels.ViewModels"));