You’ve spent months or years building a robust web application with dozens of features and an established user base. One day, the boss visits and gives you a simple, yet terrifying requirement: “We need a Xamarin app.” If you’ve only worked with MVC Web projects before, starting a new Xamarin development project can be overwhelming. Everything from learning XAML’s quirks to wrapping your head around the MVVM pattern can lead a developer to forget about the basics while trying to keep up with the demands of your deliverables. Enforcing some basic principles during Xamarin development can grant you a huge advantage.

Adopt and enforce code conventions

While you and your team scramble to assimilate an onslaught of new patterns, languages, and development ideals, every feature branch may feel like a development spike. It’s easy to quickly accumulate a lot of technical debt as each developer imparts their own coding style into their pull requests. Before you start (or now, if you have already started), develop and enforce conventions and coding standards. Your team’s code should appear as if written by only one developer.

If you haven’t already established coding conventions, you can start with Microsoft’s own recommendations and customize to your liking, tailoring it to fit the needs of your organization. You should also utilize tooling (such as ReSharper), and tooling configuration files (such as [.editorconfig] and [*.DotSettings] files) to persist configurations that can be shared across environments and stored in source control. You can also “level up” your standards by implementing and enforcing Clean Code principles.

Use strongly-typed binding contexts

A strongly-typed context in XAML has a simple requirement that throws a wrench in the web-developer mindset: your ViewModel must have a parameter-less constructor! Many new Xamarin developers will immediately dismiss this, as it goes against basic web-app fundamentals, like using dependency constructor injection. However, Xamarin.Forms’s built-in service locator DependencyService  provides easy access to dependencies, which we can still manage in the constructor.

Set the binding context in XAML:

<ContentView.BindingContext>
    <local:ProductDetailViewModel />
</ContentView.BindingContext>

Resolve dependencies through DependencyService in ViewModel constructor:

public ProductDetailViewModel()
{
	_localize = DependencyService.Get<ILocalize>();
	_navigationService = DependencyService.Get<INavigationService>();
}

The advantages you gain through this approach are many, including refactoring support, design-time confirmation of XAML properties, and ease of maintenance and debugging. Additionally, it’s easier to read XAML when you can use Visual Studio’s built-in features to navigate directly to reference properties and commands.

Learn the basics of MVVM

It can be difficult to translate from the widely popular MVC pattern in web development to the MVVM pattern used in Xamarin. To further the issue, there is a distinct lack of consistent guidance on the internet about how to apply Xamarin in your architecture. While you are forming your own opinion on MVVM with Xamarin, consider these basic guidelines:

1. Avoid dependency on third-party MVVM framework libraries

MVVM Libraries are very opinionated about many core aspects of Xamarin development ( navigation, dependency injection, etc). This leads new Xamarin developers to adopt their patterns without understanding why they matter. Instead of jumping into a complicated over-the-top framework like Prism or even opting for a smaller alternative like MVVMLight, consider starting with your own implementation of the core features these libraries offer.

For example, begin with implementing your own [BaseViewModel] and MVVM helper methods like [SetProperty]. Keep your code lightweight, and only add features as needed. As your project grows, you’ll have a clearer understanding of what additional problems need to be solved, and which libraries are better suited to solve them.

protected void SetAndRaisePropertyChanged<TRef>(
	ref TRef field, TRef value, [CallerMemberName] string propertyName = null)
{
	field = value;
	PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

2. Avoid ViewModels with domain object properties

You should not expose domain objects to your views (ever). Instead, your ViewModels should have a simple property graph for the View, hydrated by the ViewModel. If you find yourself building complex object graphs for your view, it’s typically an indicator that one or more child views may be appropriate.

3. Avoid passing state data to child ViewModels

Each view and child view should be considered a series of components that are completely in charge of their own state. Parent views should not pass state data to children, but instead pass an [id] or [key] allowing the child to fetch its own state. This simplifies your models for both the parent and the child, and avoid having hard dependencies between the two. Furthermore, you should bubble up state changes using Xamarin.Forms MessagingCenter, allowing parents (and any other listeners) to update their state.

In your ViewModel:

public ProductDetailViewModel(int productId)
{
	this.productId = productId;
}

public override async Task InitializeAsync()
{
	await RequestProductDetailAsync();
}

And in your Code Behind Class:

protected override void OnAppearing()
{
	base.OnAppearing();
	
    	ViewModel.InitializeAsync();
}

Adopt and enforce XAML style guidelines

XML and XAML have a (justified) reputation of being notoriously hard to parse/read quickly. If you haven’t lived in the XAML world a long time, then it takes a lot of work just to understand what’s going on with the code. You can establish (and enforce) some basic coding style that will make everyone’s life easier.

1. Place attributes on separate lines

Before: Attributes set in-line:

<Button x:Name="refreshButton" Margin="{StaticResource DefaultMargin}" Command="{Binding RefreshCommand}" HorizontalOptions="Center" IsVisible="false" Style="{StaticResource DefaultShadowfullButtonStyle}" Text="Try reload similar and&#x0a;also bought products">

After: Each Attribute gets its own line:

<Button x:Name="refreshButton"
    	Margin="{StaticResource DefaultMargin}"
    	Command="{Binding RefreshCommand}"
    	HorizontalOptions="Center"
    	IsVisible="false"
    	Style="{StaticResource DefaultShadowfullButtonStyle}"
    	Text="Try reload similar and&#x0a;also bought products"
    	>

3. Give controls a name
Naming a control makes it easier to determine its purpose. Additionally, if a developer has to think about naming a control, they may realize that the control is unnecessary and a simpler approach can be found.

4. Separate controls and components with a blank line
Break up the wall of XAML by using intentional whitespace. Using a blank line between significant chunks of XAML will help reviewers be able to visually identify the components of the markup.

<StackLayout Orientation="Horizontal">

	<Image Source="star"
       	Style="{StaticResource StarImageStyle}"
       	/>

	<Image Source="star"
       	Style="{StaticResource StarImageStyle}"
       	/>

	<Image Source="star"
       	Style="{StaticResource StarImageStyle}"
       	/>

	<Image Opacity="0.5"
       	Source="star"
       	Style="{StaticResource StarImageStyle}"
       	/>

	<Image Opacity="0.5"
       	Source="star"
       	Style="{StaticResource StarImageStyle}"
       	/>

	<Label Style="{StaticResource BrandonGrotesqueMediumSmallFontStyle}"
       	Text="234 Customer reviews"
       	VerticalOptions="Center"
       	>

    	<Label.Margin>
        	<Thickness Left="{StaticResource 0.5xDefaultMargin}" />
    	</Label.Margin>

	</Label>

</StackLayout>

4. Play it smart with resource dictionaries
First, avoid over-using resource dictionaries. If you have styles or templates that are used exactly once, then just put them in-line. 

Beyond these one-offs, utilize resource dictionaries to collect and manage your styles and templates. You should keep these resources separate from your XAML UI definition files, and reference them via [ResourceDictionary.MergedDictionaries]. Furthermore, application-wide dictionaries should be defined only once and referenced by all views that utilize them.

It’s important to organize your resources so that it’s easy to find them. For example, Microsoft’s Tailwind Traders reference application organizes their resources like this:

MTT Resources

 

 

 

And [GlobalStyles.xaml] contains nested references to the other resource files, making it easy to pull them into a view.

<ResourceDictionary.MergedDictionaries>
	<local:FontStyles />
	<local:Sizes />
	<local:Styles />
</ResourceDictionary.MergedDictionaries>

Key Takeaways

Adapting and enforcing core design principles to Xamarin development will grant you an enormous advantage when beginning Xamarin development. Don’t let the chaos of adopting a completely new tech paradigm make you forget your fundamental development philosophies. Start with the basics, and build from there.

Let's Talk

Have a tech-oriented question? We'd love to talk.