Declarative Code-Based Xamarin.Forms UI using CSharpForMarkup and Continuous

When it comes to UI for Xamarin.Forms, there's no denying that using XAML to create them (rather than code) is the widespread community preference. Sample a set of posts from Planet Xamarin or submissions for the recent Visual and CollectionView challenges and you'll find examples of coded UI are far and few between. In a recent talk (see end of post) I presented a somewhat tongue-in-cheek comparison of code and XAML popularity in the aforementioned challenges:

No prizes for guessing who the one person is πŸ‘€

Still, discussion regarding code and XAML occurs quite frequently in various arenas. Lately, the presence of alternatives like Flutter and Apple's recent SwiftUI announcement have brought more attention to the topic, as well as increased the discussion around alternate architectures like MVU. I watch these with interest but I find my motivations are simpler - I write my Forms UI in code because before that I was writing iOS UIs in code, and I like to use Continuous for hot reload. When I started introducing Xamarin.Forms into my projects using Forms Embedding, continuing to use code was a straightforward decision.

A twitch stream

David Ortinau spotted the use of coded UI in the Xamarin.Forms UI challenges and invited me to guest on his Twitch stream and demonstrate what the experience of writing your UI in code can be like. You can watch back the stream, in which I walked through building out the login/signup page for Xappy here.

There were two helpers I used in the stream to improve quality of life when writing UI code, @vincenth_net's CSharpForMarkup and @praeclarum's Continuous, which I'll talk a little about here.

CSharpForMarkup

Using C# to build Xamarin.Forms UIs directly can be a little awkward, and one of the projects I quickly came across when first starting out with code was CSharpForMarkup - a set of helpers that aims to let you use a declarative style of C# code for Xamarin Forms UI. CSharpForMarkup wraps and abstracts Xamarin.Forms UI actions that are unweildy to handle in code, allowing you to write concise, readable, declarative and maintainable user interfaces in C#. Based on your preference, you can use the helpers to produce 'code that looks like XAML', or you can produce code that favours conciseness whilst still remaining readable. This example from the readme demonstrates that idea a little:
Being fully contained within a single .cs file of helper methods, CSharpForMarkup is easily integrated into a new or existing project. You can use them 'just' as helper methods, or you can apply the techniques and practices described on the readme page to help drive a consistent code style across your project. One major peril of writing coded UI is the fact that with code 'anything is possible', including overly clever or specialised solutions. With CSharpForMarkup, you can apply and enforce a consistent, coded-based style for your UI development, and produce code that makes you feel good writing it.

As you might guess, use of CSharpForMarkup was a key focus of the stream. Afterwards, Vincent offered to give the code the full CSharpForMarkup treatment - with all the conventions he recommends - and the final result now lives in Xappy. One thing I also did on the stream is demonstrate a "DSL"-style of UI specification, which relied on dedicated helper methods to reduce the amount of boilerplate in the class. Although I tend to think the declarative style is the right balance of consistency / conciseness / maintainability, in specific cases you might find a DSL style justified.

Continuous

Continuous is a hot reload plugin created by the very excellent @praeclarum several years ago. I have used it on many projects since then and help keep it alive by updating the VS4Mac plugin when the IDE goes through major changes (moving to roslyn, using the new code editor). I am a huge fan of Continuous and use it whenever I work on apps. Besides the stream above, you can see some examples of Continuous' power in videos I've posted in the past:

Hot reloading ARKit with Continuous

Hot reloading a 'real world' complexity app with Continuous

Over that time, I've learned how to make Continous sing, and have used it in all manner of scenarios, but the methods for doing so are not always pretty. I am used to them all but have to hestitate when I think about the experience that someone new might have after watching my examples. From time to time I have worked on a rethink of Continuous that addresses some of the main pain points (who knows if I will ever finish it), and as an experiment I ported some of those ideas back to the version I used on stream, which is what allowed for the deeper and cleaner integration with Xamarin.Forms Shell. Given the effectiveness of these changes, and how easy they were to integrate, I'd like to apply them back to the core library and maybe do a write up of how to effectively make use of them.

A presentation

Off the back of the Twitch stream, I also gave a quick talk on the same topic at the Queensland C# Mobile Developers meetup group's June 2019 Meetup. This one was a little more hurriedly put together than my normal talks, but (hopefully) gave a good walkthrough of CSharpForMarkup by example and focussed on specific code-based scenarios with a little bit of live coding to demonstrate how the library improves them. Slides for the talk are below.

(Yes, the fringe languages comment was a joke - I love my F#).

Slides (28): PDF