user7288468
user7288468

Reputation: 13

Xamarin.Forms Caliburn.Micro - Associate multiple Views with a single ViewModel

I am looking for some guidance on how to Associate multiple Views with a single ViewModel. We are developing an app using Xamarin.Forms Portable (VS.NET 2017) and Caliburn.Micro as an MVVM framework.

In App.cs, DemoView is invoked via the below line and everything works fine:

Now, the issue is that we need to load different Views for Mobile and Tablet. I created a new folder structure under /Views as follows: - /Views/Demo/Mobile.xaml - /Views/Demo/Tablet.xaml

The question is how to load the relevant View based on a condition (Device.Idiom), knowing that there needs to be a way to associate the above 2 views with DemoViewModel.

Does this mean I would still require a /Views/DemoView.Xaml (knowing that is it already associated to /ViewModels/DemoViewModel.cs) that would behave as an intermediary and load the correct View based on the the condition mentioned?

I should flag that the Views we seek to load are Tabbed Pages that will load other pages in it in the DemoViewModel (which implements Conductor.Collection.OneActive) by adding other ViewModels to the Items collection.

Thanks, P.

Upvotes: 0

Views: 175

Answers (1)

Barnstokkr
Barnstokkr

Reputation: 3129

You will have to setup some custom conventions.

If you always need to load different views for phone and tablet, then you can configure the area where Caliburn searches for the View or ViewModels by configuring the Type Mappings.

App.xaml.cs

protected override void Configure()
{
    TypeMappingConfiguration config = null;
    if( Device.Idiom == TargetIdiom.Tablet)
    {
        config = new TypeMappingConfiguration
        {
            DefaultSubNamespaceForViews = "Tablet.Views",
            DefaultSubNamespaceForViewModels = "Common.ViewModels"
        };
    }
    else
    {
        config = new TypeMappingConfiguration
        {
            DefaultSubNamespaceForViews = "Mobile.Views",
            DefaultSubNamespaceForViewModels = "Common.ViewModels"
        };
    }
    if(config != null)
    {
       ViewLocator.ConfigureTypeMappings(config);
    }
}

If you share most Views across idioms, then you can specify Views for specific View Models

protected override void Configure()
{
    if( Device.Idiom == TargetIdiom.Tablet)
    {
        ViewLocator.AddNamespaceMapping("Common.ViewModels.Demo", "Tablet.Views");
    }
    else
    {
        ViewLocator.AddNamespaceMapping("Common.ViewModels.Demo", "Mobile.Views");
    }
}

This will map

Tablet: Common.ViewModels.DemoViewModel to Tablet.Views.DemoView

Mobile: Common.ViewModels.DemoViewModel to Mobile.Views.DemoView

And you can always do a hybrid of these.

Upvotes: 2

Related Questions