When you start reading into Mvvm, you usually find some articles about INotifyPropertyChanged, Bindings, Commands and reducing Code Behind. Once you are past that point, information gets rare.
But there’s a lot more to Mvvm than just these basic concepts. Especially, if you want to span that architecture cross platform with Xamarin.
This series explains a reference architecture for cross platform Mvvm, which we used in several projects. In the coming weeks, I am going into details for all steps along the road.
It all began in the model…
Add a PCL: Project.Sample.Domain
We usually start with the domain model for our app (yes, we used DDD, but even if you don’t’ this is a good starting point). First step is to create C# classes for all of our domain entities like News, Users, Products or whatever there is. These tend to be just dumb classes with a bunch of getters and setters for most cases.
Once we’ve got the things we work with, we start wrapping them some services around them that know how to obtain these models and how to perform operations on them. Until now, our project looks somewhat like this:
- [Design considerations for the domain model.]
And then, things got connected…
Add a PCL: Project.Sample.Domain.RestApi
Next, we connect our app to the services. In most cases, these are already in place: Instagram Api, Office 365 Api, some Azure Mobile Service, etc.
What we have to add are the clients, that connect to these services and convert between their data transfer objects and our model. This usually involves Json.Net, HttpClient and a lot of .FromJson() methods.
This is also the point in time to write some integration tests to see if your clients work correctly. Doing that now spares a ton of debugging time later.
- [Design considerations for service connectors]
Adding some state…
Add a PCL: Project.Sample.Infrastructure
It’s about time we start making a real application out of all those connected services and models we got right here. So now we got to stop thinking in domain terms and move over to application design (no, not those fancy UI stuff yet; but getting close!).
View Models are the next wrapper around our domain: They know how to uses the services, how to handle all the exceptions (yes, ALL of them) and besides that, they hold the “state” of the application.
State means, they know what data needs to be loaded, what has been loaded already, where we can go and what we can do from where we are. Despite of having just such a small box in the architecture diagram, the ViewModels are our real champions.
- [Handling errors: The exception barrier]
- The view model method template
Fine, can we do Android now?
Add: Project.Sample.Clients.AndroidApp, Project.Sample.Clients.WindowsApp, …
NO! Do windows first. It’s much easier and way more fun. But yeah, this is where you add all your client projects.
We’ve come pretty far already, but clients still have a lot of duties: They provide configuration for all the models, viewmodels, services, clients, etc.; They have to connect the UI with the viewmodels and of course they contain the UI itself.
All that UI stuff are left uncovered here, because when using Xamarin, you are just writing native code with camel cased naming.
Client projects consist of 3 parts:
- The UI with all its Activities, ViewControllers, etc.
- Platform specific implementations of interfaces required by all the underlying components.
- Connectors to interact with viewmodels
Configuration for the services is usually done using a dependency injection container and a service locator.
As connectors, you use Xaml bindings on windows and everything is nice and easy. Value converters are also a part of these connectors. You can use a framework like MvvmCross (mvx) to get something similar to bindings on other platforms as well.
If you won’t or can’t use Mvx, looking at windows’ compiled bindings (aka x:Bind) is a good option: It isn’t exactly human readable, but you can easily write something similar for android and iOS when getting down into their ListAdapters an ViewControllers.
- [Learn from Xaml’s compiled bindings]