MvvmCross & Separate Tablet UI

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

🇺🇦 Bohdan Benetskyi
3 min readJan 29, 2021

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?

<ProjectFolder>
=> Pages
=> Mobile
XMobilePage.xaml
YMobilePage.xaml
=> Tablets
XTabletPage.xaml
YTabletPage.xaml
=> PageModels
=> Base
BaseXPageModel.cs
BaseYPageModel.cs
=> Mobile
XMobilePageModel.cs
YMobilePageModel.cs
=> Tablets
XTabletPageModel.cs
YTabletPageModel.cs

And how does this solution look like from a code?

--

--