WP7 ViewModels in different assembly

Topics: Bootstrappers & IoC
Mar 13, 2012 at 10:18 PM
Edited Mar 13, 2012 at 10:18 PM

I'm having trouble loading a ViewModel from another assembly(project) in my solution, I've gone over the documentation wiki but I'm new to CM and IoC and I'm a bit stumped as to what is causing the problem!

I have my VS2010 Solution set-up as follows;

 

Project 1 (Windows Phone Class Library)
CompanyName.ProjectName.Core
-ViewModels (folder)
--MainPageViewModel.cs

Project 2 (Windows Phone App - set as Start-up Application)
CompanyName.ProjectName.AppName
App.xaml
AppBootstrapper.cs
-Views (folder)
--MainPage.xaml

In AppBootstrapper I have;

 

protected override void Configure()
{
    container = new PhoneContainer(RootFrame);
    container.RegisterPhoneServices();
    container.PerRequest<RepositorySqlCe>();

    container.PerRequest<MainPageViewModel>();

    AddCustomConventions();
}

protected override void OnStartup(object sender, StartupEventArgs e)
{
    ViewModelLocator.AddSubNamespaceMapping("AppName", "Core");
    ViewLocator.AddSubNamespaceMapping("Core", "AppName");

    var context = new ItemContext();
    if (!context.DatabaseExists())
    {
        DataHelper.MoveReferenceDatabase("RefData.sdf");
    }
    base.OnStartup(sender, e);
}

protected override IEnumerable<Assembly> SelectAssemblies()
{
    var assemblies = new List<Assembly>();
    var refAssemblies = AppDomain.CurrentDomain.GetAssemblies();

    assemblies.AddRange(refAssemblies);
    assemblies.Add(Assembly.Load("CompanyName.ProjectName.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
			    
    return assemblies;
}

 

If I move my ViewModels into Project 2 (in a ViewModels folder) then everything works as expected. From the wiki the ViewModelLocator.AddSubNamespaceMapping option to me sounds like the correct one, but I've tried all manner of other options and I can't get it to pick up the ViewModels from the external assembly. 

Can someone point me in the right direction please? :)

Mar 14, 2012 at 11:29 PM
Edited Mar 14, 2012 at 11:36 PM

OK!  I got it working :) All the changes are in the OnStartup method.

protected override void Configure()
{
    container = new PhoneContainer(RootFrame);
    container.RegisterPhoneServices();
    container.PerRequest<RepositorySqlCe>();

    container.PerRequest<MainPageViewModel>();

    AddCustomConventions();
}

protected override void OnStartup(object sender, StartupEventArgs e) 
{
    var config =  new TypeMappingConfiguration
    {
        DefaultSubNamespaceForViewModels = "CompanyName.ProjectName.Core.ViewModels,
        DefaultSubNamespaceForViews = "CompanyName.ProjectName.AppName.Views" 
    };

    ViewLocator.ConfigureTypeMapping(config);
    ViewModelLocator.ConfigureTypeMapping(config);

    var context = new ItemContext();
    if (!context.DatabaseExists())
    {
        DataHelper.MoveReferenceDatabase("RefData.sdf");
    }

    base.OnStartup(sender, e);
}

protected override IEnumerable SelectAssemblies() 
{
    var assemblies = new List();
    var refAssemblies = AppDomain.CurrentDomain.GetAssemblies();
    assemblies.AddRange(refAssemblies);
    assemblies.Add(Assembly.Load("CompanyName.ProjectName.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
    return assemblies; 
}

Happy days!

Mar 19, 2012 at 10:06 PM

You could get away with configuring the mappings this way as well:

var config = new TypeMappingConfiguration
{
    DefaultSubNamespaceForViewModels = "Core.ViewModels",
    DefaultSubNamespaceForViews = "AppName.Views"
};
Apr 5, 2012 at 8:44 AM

That's great - thanks for the reply, yours is a bit more tidy :)