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?
<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?