MvvmCross & Separate Tablet UI

How to make separate View’s for Tablet, Phones, Desktops and other device families

Hi folks, it’s so easy with Xamarin.Forms check TargetIdiom 🤩 with Device.Idiom and make checks right in your XAML Code or C# Code Behind. But if we have a completely different UI for Tablets or should change it more than 60–70%, our XAML code will look like a mess ☹️, it will be SO HARD to navigate between controls and parts of different sections in UI.

No, no, no make a lot of custom controls will not solve our problem, we are in real life mostly handle with complex UI components, a lot of user interactions and gestures on it.

So, what we can do with all of that? (you may ask me 😎) — Create a separate View for Tablets and separate View for Phones 🥳. But how to make it right with MvvmCross?

This what I’ve asked in StackOverflow, and below is what I tried and how to solve it in the end:

First Solution 📵

ℹ️ Make two Pages — LoginPage and LoginTabletPage with the same LoginPageModel.

📵 This does not work, because MvvmCross does not allow to have multiple views for each ViewModel and throw runtime Exception.

Second Solution 📵

ℹ️ Make own NavigationService inherited from MvxNavigationService and use from the interface IMvxNavigationService. With this approach, we don't need to re-write all files for Phones, all will be handled in new NavigationService.

NavigationService - will override Navigation and according to Device.Idiom navigate to XPageModel or to XTabletPageModel

📵 This does not work, because MvvmCross can’t handle replacing of MvxNavigationService because created in MvxSetup.cs:

iocProvider.LazyConstructAndRegisterSingleton<IMvxNavigationService, IMvxViewModelLoader, IMvxViewDispatcher>((loader, dispatcher) =>
new MvxNavigationService(loader, dispatcher));

Loader and Dispatcher are not available from our layer and throws Runtime Exception.

Third Solution 👌

Eject all navigations to virtual methods. Create an abstract BaseXViewModel where all logic, commands will be placed. All navigation methods should be abstract and re-written on delivered classes like XTabletViewModel, XPhoneViewModel, XDesktopViewModel and others. Also, where it’s needed base(shared) logic methods can be made virtual and overridden in delivered ViewModels.

👌 This is a pretty simple approach and gives us the possibility to easily modify the behaviour of navigation at pages and the logic.

How does this solution look like from a project?

=> Pages
=> Mobile
=> Tablets
=> PageModels
=> Base
=> Mobile
=> Tablets

And how does this solution look like from a code?

Microsoft MVP | C# .Net | Xamarin