In a recent blog post, I showed the C# best practices we use at my current placement. Today, the Xamarin best practices:
Xamarin
Best Practices
The Do’s 
Catch XAML Errors Early
Add the following attribute to code behind in order to improve performance and catch xaml errors early.
[assembly: XamlCompilation (XamlCompilationOptions.Compile)]
By convention the identifier for the ViewModel is vm (not Vm or vM)
The only code in code-behind (e.g., foo.xaml.cs) should be
- initialize in the constructor
- create the view model
- assign the datacontext to the view model
- call the viewmodel’s Initialize method
- Lifecycle methods such as OnAppearing and OnDisappearing
Why: we want to keep the code behind as sparse as possible. Unit testing requires reaching into code and that is infinitely easier with a viewmodel.
Every viewmodel should have an initialize method called from the code behind.
Why: Having an initialize method keeps most of the code for the vm out of the constructor. This is recommended practice by Microsoft, and allows for async methods.
Create viewmodel name by appending “viewmodel” to the xaml name
LigthController.xaml
LightController.xaml.cs
LightControllerViewModel.cs
Why: It is far easier to find the file you want if we follow a convention.
Use commands rather than event handlers
// wrong - handled in code behind
<button Text="Divide by 2" Clicked="onClick" />
//correct - handled in viewmodel
<button Text="Divide by 2" ClickedCommand="{Binding DivideBy2Command"
Why: It is much easier to write unit tests when the event handler is in the viewmodel. Update: Use the Xamarin Community Toolkit to create commands out of events.
ListView ItemSource should bind to Observable Collections instead of Lists
Why: Observable Collections provide notifications when items get added, removed, or when the whole list is refreshed. Lists do not provide these notifications. Warning, there is no automatic push notification if a member of the list is changed.
Set BindingContext in ctor of the View CodeBehind
Why: This will prevent timing issues that may prevent the Content Page Title from displaying
Place async method calls in OnAppearing in the View CodeBehind rather than in the constructor
//wrong public PointsListView() { viewModel = new PointListViewModel(pointService, Device, SelectedModule, ObjectType); Task.Run(async()=> await viewModel.PopulateMenuOptions()); } //correct public PointsListView() { } protected override async void OnAppearing() { viewModel = new PointListViewModel(pointService, Device, SelectedModule, ObjectType); await viewModel.PopulateMenuOptions(); }
Why: The ctor should only be initializing the view and should not make calls to controller.
And Microsoft support said so
The Don’ts 
Do not assign more than one view to a view model. Generally speaking, it should be one view to one view model.
Do not put Xaml in templates in App.xaml. Put the Xaml in the Xaml file.
Why: App.xaml quickly becomes bloated and hard to work with. Having the Xaml in the Xaml file is natural and helps create the troika we want: foo.xaml, foo.xaml.cs and fooViewModel.cs.
Do not pass view modes to methods of other pages
Avoid Xaml file names ending in “view”
LightControllerView.xaml
LightControllerView.xaml.cs
LightControllerViewViewModel.cs
Why: Adding view to a view file is redundant and it makes reading the name of the ViewModel more difficult.
Do not end async method names with ‘Async’
Why: It is easy to forget.