Nick's .NET Travels

Continually looking for the yellow brick road so I can catch me a wizard....

Building a Number Plate Identification Service in 5 Minutes with Microsoft’s Custom Vision Service

I woke up this morning pondering how hard it would be to use Microsoft’s Custom Vision service to build a service which could be used to extract out number plates from an image. In this post I’m just going to cover the object detection phase of this work, which identifies where on an image a number plate exists. A subsequent phase would be to use the OCR service that’s part of the computer vision services to extract the number plate itself.

I decided to see how far I could get using the out of the box offering at CustomVision.AI. After signing in (you’ll need an account linked to Azure) you’re presented with the option to create a new project:

image

Clicking New Project I needed to fill in some basic information about my project and the type of project I’m building. In this case we’re going to use object detection in order to identify number plates within an image

image

After hitting Create Project I’m dropped into the project dashboard which essentially covers three areas: Training, Performance and Predictions. Rather than this being a strict sequence, the idea is that you’ll go back and forth between these areas gradually refining and improving the model. As we don’t already have a model, we need to start by adding some images to train with.

image

As I don’t have an archive of photos with number plates, I decided to grab a selection of images from Google. You’ll notice that I include “with car” in my image search – we’ll talk about why this is important in a minute

image

I downloaded around 30 of these images (you’ll need at least 15 to train the model with but the more images the better). Clicking on Add images give me the ability to upload the images I downloaded from Google image search

imageimageimageimage

The images I uploaded appeared as “untagged” – essentially I haven’t identified what in each photo we’re looking for. To proceed, I need to go through each image, and select and tag any areas of interest

image

Rather than selecting each individual image, if you hit Select All and then click on the first image you can step through each image in turn

image

If you hover over the image, you’ll see that there are some suggest areas that appear with a dotted outline.

image

You can either click the suggested area, or you can simply click-and-drag to define your own area

image

In my first attempt I assumed that I should be marking just the area that includes the text, because the registration number is what I want as the eventual output. However, this didn’t seem to give very accurate results. What the service is great at is identifying objects, and rather than defining areas that show a number plate, I was just getting it to recognise text, any text. In my second attempt I defined regions that bounded the whole number plate, which gave me much better results.

image

After going through all of the images and tagging them, all the images should appear as tagged and you should see a summary of the number if images for each tag

image

Now to hit the Train button (the green button with cogs in top right corner). Once training is done you can see some key metrics on the quality of the iteration of your model. In general terms the higher the percentage the better; and the more training images you provide and tag, the better the model will get.

image

After you’ve run Train the first time, you actually have a model that you can use. From the Predictions tab you can see information about the endpoint that’s available for your app to call in order to invoke the service.

image

What’s really great is that you can click on Quick Test and then supply an image to see how your service performs.

image

In this case the service identified one area that it thinks is a number plate with a probability of 92.4%. The next step would be to pass the number plate through an OCR service in order to extract the registration number.

All of this was setup, trained and made available as a service in under 5 minutes (excluding the time spent re-tagging the training images to include the whole number plate, rather than just the text).

Using IntelliTest in a .NET Standard Library

Today I was reviewing some of the test cases we have for BuildIt.General – these are a bit dated now as they were created with MSTest using IntelliTest. Recently we’ve updated the BuildIt libraries to target .NET Standard and to support multi-targetting. Unfortunately, whilst the test cases continue to run, I was unable to run IntelliTest in order to add test cases for some of the new features we’ve added recently. As this Stack Overflow question confirms, IntelliTest is only supported on .NET Framework class libraries. What’s worse is that IntelliTest is only supported on old style csproj projects.

In order to get IntelliTest to work for BuildIt.General I created a new .NET Framework class library, BuildIt.General.FullFramework.csproj, which I placed into the same folder as BuildIt.General.Tests (putting it into the BuildIt.General folder causes all manner of weirdness due to different csproj formats not playing nicely together).

image

For each file in BuildIt.General that I wanted to use IntelliTest to generate test cases I added the file as a link to the BuildIt.General.FullFramework project. IntelliTest can be run by right-clicking within the method to be tested, selecting IntelliTest –> Run IntelliTest.

image

The IntelliTest output is shown in the IntelliTest Exploration Results window, from which each test can be saved.

image

More information on IntelliTest can be found on the docs website.

Calculator App in 100 Lines

A bit of a challenge was set off over the last week which I think started after Don Syme tweeted about a Calculator sample app that had been done in 95 lines of code

image

Github repo at https://github.com/nosami/Elmish.Calculator and was based off a Xamarin sample https://github.com/xamarin/mobile-samples/tree/master/LivePlayer/BasicCalculator

As there was a bit of discussion as to the pros and cons of different mobile platforms, some of the community set out to see how many lines of code it would take them to build the same sample. Thomas tweeted about doing it in Flutter which originally came in a 93 lines of code (I question the choice of colours and definitely prefer the colours in the original sample)

Update: In my original post I didn’t link to the correct info. Thomas’ calculator came in at 90 lines of code and sticks with the original colour scheme

Github: https://github.com/escamoteur/flutter_calculator

There was an alternative colour scheme proposed which came in at 93 lines of code

image

Github repo: https://github.com/fmatosqg/flutter_calculator

I tweeted in jest that a XAML app wouldn’t get out of bed for less than 100 lines of code, and sure enough when I did a very quick attempt it came in at approximately 70 lines of XAML and the same again for codebehind, so ~140 lines all up. I think with a bit of optimising I could get it down to say 120 lines but the reality is that XAML is verbose and that there is a cost associated with splitting the code between XAML and codebehind. Of course, if I’d actually applied an MVVM pattern it’d probably jump up to say 150 lines of code.

One way I could optimise this to get a result closer to either the Elmish or Flutter examples would be to do all my layout in code. I mentioned in my post on using declarative C# that following Vincent’s example of using extension methods you can easily do your layout in C# and avoid any of the overhead of splitting out XAML, C# and ViewModel code.

The question I ask is what do we lose in defining layout in code. As Vincent points out in his example, the answer can be that we lose very little but my concern is that whilst defining layout in code works for seasoned developers, how will it go with more junior developers?

For those who have been building apps for long enough, you’ll remember how we despised building Windows Forms applications because all the layout was done in code – sure there was a design experience, but before long you were writing a lot of logic to manipulate the UI which resulted in mal-formed code that was a pain to debug/maintain. Is this where we’re going to end up with all these code-first approaches to defining layout? (and this question isn’t about which platform is better, it’s about declarative over coded UI).

By way of example, stop and take a look at the code Thomas put together in his Flutter example – very efficient but imagine it on a much more complex application. You can quite easily see how it’s going to become hard to understand/follow for a developer who has to maintain it.

Redux and the State of My XAML Application (part 3)

This is the final part in this series looking at using Redux in a XAML application. Previous parts:

- Part 1 - https://nicksnettravels.builttoroam.com/post/2018/05/15/Redux-and-the-State-of-My-XAML-Application-(part-1).aspx

- Part 2 - https://nicksnettravels.builttoroam.com/post/2018/05/16/Redux-and-the-State-of-My-XAML-Application-(part-2).aspx

At the end of Part 2 I left you wondering what magic I’m using to prevent the entire list being refreshed as items were being added/removed from the Family. In this post we’ll look at what’s going on behind the scenes.

Let’s start with the bolded text from the XAML in Part 2 – I’ve included it here so you don’t need to go back and look.

<Page.Resources>
   <converters:ImmutableDataConverter x:Key="ImmutableDataConverter"/>
</Page.Resources>
<Grid DataContext="{Binding Converter={StaticResource ImmutableDataConverter}}">

So the secret ingredient is the ImmutableDataConverter which takes the current DataContext (which will be an instance of the MainViewModel) and returns an object that will become the DataContext for the rest of the page. The question is, what is this object and what does it do?

If you recall the issue we saw when we didn’t use the ImmutableDataConverter is that when the Data property on the MainViewModel changes (ie raised the PropertyChanged event) every data bound element on the page is refreshed. What we want is that only the elements on the page where data has changed should be updated. To do this, we need to step through the Data object and only raise PropertyChanged for the parts that have actually changed. Based on this description, the ImmutableDataConverter has to have the smarts to a) prevent PropertyChanged causing the entire UI to refresh and b) be able to iterate over every object in the Data object graph and where appropriate raise the PropertyChanged event.

Behind the scenes the ImmutableDataConverter is super simple – all it does is create an instance of the ImmutableDataWrapper<T> class. It uses a small piece of reflection to determine what the generic parameter should be based on the implementation of the IHasImmutableData interface on the MainViewModel.

The ImmutableDataWrapper<T> exposes a single property Data, of type T (and it’s no coincidence that this is the same as the IHasImmutableData<T> interface which also exposes a property Data, of type T – thereby making it simple to add the ImmutableDataConverter without changing any other lines of XAML). It also listens to the PropertyChanged event on the source entity, which in this case is the MainViewModel. Now instead of the PropertyChanged event on the MainViewModel being picked up by the MainPage, it is instead picked up by the ImmutableDataWrapper and used to invoke the ChangeData method where all the work happens.

The ChangeData method is used to compare the old Data object with the new Data object (ie the value that is set on the MainViewModel when the PropertyChanged event is triggered). It does this by using reflection to step through each property on the Data object:

- Properties that are of value type, or string, are updated on the old Data object if the value on the new Data object is different – the PropertyChanged event is raised for just that property.

- For properties that return a non-value type (or string) reflection is used to interrogate the nested entity and work out which properties need to be updated.

- For ObservableCollections some basic list change detection is used to trigger add/remove events on the collection on the old Data object – we can probably improve the logic here to be more efficient but for the moment it does the job.

As you can imagine there’s quite a bit of reflection that has to go on each time the Data object changes. Assuming that the Data object could change quite a bit, we don’t want to be doing reflection every time, which is where the TypeHelper class comes it. The TypeHelper class has some smarts of assisting with both checking to see if an entity has change, and for updating entities. Based on the type of entity, it caches methods that are used for comparison and updating entities. You can check out the TypeHelper class if you want to see more of the details

So lastly, let’s look at the requirements for the ViewModel and your Data entity:

- ViewModel needs to implement IHasImmutableData

- Data entity (and any nested entities) needs to implement INotifyPropertyChanged but also IRaisePropertyChanged – this is required so that the ChangeData method can raise the PropertyChanged on behalf of a data entity

- Properties on the Data entity (and any nested entities) should not raise PropertyChanged – otherwise there will be multiple PropertyChanged events raised

- Any collections within the Data entity hierarchy should use ObservableCollection<T>

A couple of final pointers:

- Currently this is only available for UWP – I need to implement the appropriate converter for Xamarin.Forms (and I guess WPF if anyone cares?)

- Currently this is not thread safe – make sure you update the Data property on the ViewModel on the UI thread.

Redux and the State of My XAML Application (part 2)

In part 1 I talked a bit about the challenge that XAML based applications face when trying to use a pattern such as Redux. In this post I’m going to jump in and use Redux.NET to demonstrate the issue, and the show how we can make a small adaption to the XAML to fix this issue.

We’ll start with the basic – our application state is a Person entity, with a Name property and a Family property. The Family property is an ObservableCollection of Person:

public class Person : NotifyBase
{
     public string Name { get; set; }

    public ObservableCollection<Person> Family { get; set; } = new ObservableCollection<Person>();
}

In this case NotifyBase comes from the BuildIt.General library and implements INotifyPropertyChanged. It also implements IRaisePropertyChanged which exposes a RaisePropertyChanged method which can be called in order to raise a PropertyChanged event on the object – we’ll come to why this is important later.

Implementing the Redux pattern starts with the Store, and in this case I’m just going to expose this as a static property off the App class. In reality you’d probably register this with your IoC container and have it injected into your ViewModel but to keep things simple I’m just creating it as a static property.

sealed partial class App : Application
{
     public static IStore<Person> PersonStore { get; private set; } = new Store<Person>(reducer: PersonReducer.Execute, initialState: new Person { Name = "Fred" });

The Store of course requires a Reducer, which in this case will be the PersonReducer class

public static class PersonReducer
{
     private static Random rnd = new Random();
     public static Person Execute(Person state, IAction action)
     {
         if (action is AddAction addAction)
         {
             var newPerson = new Person { Name = addAction.NameOfNewFamilyMember };

            return new Person
             {
                 Name = state.Name,
                 Family = state.Family.DeepClone().AddItem(newPerson)
             };
         }

        if (action is RemoveAction)
         {
             var idxToRemove = rnd.Next(0, 1000) % state.Family.Count;
             return new Person
             {
                 Name = state.Name,
                 Family = state.Family.DeepClone().RemoveItemAt(idxToRemove)
             };
         }

        return state;
     }
}

As you can see from the code the PersonReducer implements two actions: AddAction and RemoveAction. We’ll create these as classes

public class AddAction : IAction
{
     public string NameOfNewFamilyMember { get; set; }
}

public class RemoveAction : IAction { }

The other thing to note about the PersonReducer is that both actions return entirely new Person entities. It also makes use of a couple of helper methods:

public static class ReduxHelpers
{

    public static ObservableCollection<T> DeepClone<T>(this ObservableCollection<T> source) where T : new()
     {
         var collection = new ObservableCollection<T>();
         var helper = TypeHelper.RetrieveHelperForType(typeof(T));
         foreach (var item in source)
         {
             var newItem = new T();
             helper.DeepUpdater(newItem, item);
             collection.Add(newItem);
         }
         return collection;
     }

    public static ObservableCollection<T> AddItem<T>(this ObservableCollection<T> source, T itemToAdd)
     {
         source.Add(itemToAdd);
         return source;
     }

    public static ObservableCollection<T> RemoveItemAt<T>(this ObservableCollection<T> source, int index)
     {
         if (index < 0 || index >= source.Count) return source;
         source.RemoveAt(index);
         return source;
     }
}

Note: These extension methods will be added to BuildIt.General in the coming days and they rely on other types/methods (such as the TypeHelper class) that are already part of the BuildIt.General library.

With the Store and Reducer defined, we can define our MainViewModel

public class MainViewModel : NotifyBase, IHasImmutableData<Person>
{
     private Person data;
     public Person Data
     {
         get => data;
         set => SetProperty(ref data, value);
     }

    public MainViewModel()
     {
         App.PersonStore.Subscribe(newData => Data = newData);
     }
}

As this code shows, when the state in the Store changes, we’re just updating the Data property on the MainViewModel, this will in turn raise the PropertyChanged event causing the UI to be re-bound. Let’s take a look at the XAML for the MainPage.xaml:

<Page
     x:Class="reduxsample.MainPage"
     xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     xmlns:converters="using:BuildIt.UI.Converters"
     mc:Ignorable="d"
     Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
     <Page.Resources>
         <converters:ImmutableDataConverter x:Key="ImmutableDataConverter"/>
     </Page.Resources>

     <Grid DataContext="{Binding Converter={StaticResource ImmutableDataConverter}}">
         <Grid DataContext="{Binding Data}">
             <Grid.RowDefinitions>
                 <RowDefinition Height="Auto"/>
                 <RowDefinition />
             </Grid.RowDefinitions>
             <StackPanel Grid.Row="0">
                 <TextBlock Text="Name"/>
                 <TextBlock Text="{Binding Name}"/>
                 <TextBlock Text="Family member to add"/>
                 <TextBox x:Name="NewFamilyMemberName"/>
                 <Button Content="Add" Click="AddFamilyClick"/>
                 <Button Content="Remove" Click="RemoveFamilyClick"/>
             </StackPanel>
             <ListView Grid.Row="1" ItemsSource="{Binding Family}">
                 <ListView.ItemTemplate>
                     <DataTemplate>
                         <Border
                             BorderBrush="Azure"
                             BorderThickness="0,0,0,1">
                             <TextBlock Text="{Binding Name}"/>
                         </Border>
                     </DataTemplate>
                 </ListView.ItemTemplate>
             </ListView>
         </Grid>
     </Grid>
</Page>

This is all stock XAML with the exception of the Bold text (which we’ll come to in a minute). First, let’s add the methods for adding and removing family members

public sealed partial class MainPage : Page
{
     public MainPage()
     {
         this.InitializeComponent();

        DataContext = new MainViewModel();
     }
     private void AddFamilyClick(object sender, RoutedEventArgs e)
     {
         App.PersonStore.Dispatch(new AddAction { NameOfNewFamilyMember = NewFamilyMemberName.Text });
     }
     private void RemoveFamilyClick(object sender, RoutedEventArgs e)
     {
         App.PersonStore.Dispatch(new RemoveAction());
     }
}

Ok, now for a minute, let’s go back to the XAML and for a minute imagine that the bold text isn’t there. Now when we run the app and click the Add or Remove button, the Data property on the MainViewModel will get repopulated – the implication on the UI is that the ListView which binds to the Family property will refresh entirely. This will cause a flicker, and will drop any selected state and/or scroll position on the list – generally a really bad user experience.

With the bold text left in the XAML, when we run the app and click the Add or Remove button, only the properties that have changed are refreshed – there is no flicker on the ListView and any selection/scroll position is maintained….. so what’s going on…. can you work out why IRaisePropertyChanged is important…. more to come in my next post.

Redux and the State of My XAML Application (part 1)

Recently there has been quite a bit of noise about new tools and technologies (eg Flutter) and how they’re going to reshape how we build mobile applications. Various developers have blown a lot of smoke into the ecosystem as they’ve thrown in the towel with one technology and jumped headlong into the unknown. In this post I wanted to explore one of the key architectural differences that has developers up in arms about.

Let’s firstly step back a few, or more, years back to the dark ages of building Windows Forms (WinForms) applications where everything was done via imperative code. Visual Studio provided some basic abstraction from designer generated code v’s developer code but other than that everything was done manually. Whilst WinForms did have a form of data binding, it was so hard to get it to work well, most apps ended up resorting to writing logic to set properties on the UI elements directly.

A little further along the timeline we see the introduction of XAML (WPF, Silverlight etc) where data binding was a first class citizen. Enter the age of the MVVM pattern which was widely adopted as it offered a great separation of concerns between the view (ie the XAML) and the logic of the app. Personally I’ve never seen MVVM as much more than just the use of data binding. Recently I’ve heard of all sorts of reasons why developers thought that MVVM was being used, such as allowing the reuse of ViewModels and/or Models across different apps – I’m not sure where this concept came from but the reality is that it never happens. I think MVVM is still just about making it easier to test the logic of the application without having to spin up the UI.

Databinding works well, allowing the UI to be declaratively defined (either in XAML or code) but it doesn’t prescribe how an application should be architected behind the scenes. There are some frameworks, such as MvvmCross that help with a lot of the boilerplate logic (app start up, DI framework, navigation etc), but that’s where the guidance ends. For simple applications this isn’t an issue, and for a lot of application complexity is kept quite low, which means that keeping business logic, and state, on a page by page basis isn’t an issue. However, over time applications grow, and the complexity increases. This was identified by Facebook as the complexity of their website grew and they needed a more effective way to manage state. At this point I’m going to skip ahead to Redux (there’s more background at redux.js.org) which aims to solve the issue of state management within an application using a mono-direction flow to ensure consistency of state. I’m also not going to proclaim to be a guru on Redux, I just want to point to how it supports a new wave of React style development. The essential concept is that app state is immutable and that any changes result in a new state.

If you take a look at the way that Flutter builds their UI, the layout is made up of a sequence of widgets generated each time the build method is invoked. As the state of the application changes, a call to setState will trigger the build method to be run, yielding a completely new set of widgets that will be painted in the next pass to the screen. It’s pretty obvious that if the app state is being regenerated on each change (ie Redux pattern), this plays nicely with the setState/build flow that’s core to Flutter.

So, the question is – if we want to take advantage of Redux, do we have to abandon ship and start building Flutter apps? Well if you want to give up on all the years of experience you have, the mature ecosystem, and all the platforms that Flutter doesn’t support, sure, why not, but I do feel that in the absence of other reasons, that this is a bit like throwing the baby out with the bathwater.

To rephrase the question – in a XAML application, how do we take advantage of Redux? Well the good news is that half the work is already done – Redux.NET. However, I would caution you not to follow the rather simplistic examples given on the project website which essentially disposes of the use of data binding – if you’re going to do that, just go build your app using a different technology. Instead, we need to think a bit more about how we can marry the concept of immutable state with data binding.

The naïve approach is to expose the state of the application as a property and then every time the state changes, we update the property with the new value. For example the following ViewModel exposes a Person object which represents the current state of this simple application.

public class MainViewModel : INotifyPropertyChanged
{
     private Person data;

    public Person Data
     {
         get => data;
         set => SetProperty(ref data, value);
     }

This approach will work and as the Data property is updated with new Person entities, the data bound UI will update accordingly. However, if the Person object is moderately complex, with nested data bound properties, when you update the Data property there will be some nasty UI artefacts – this is because triggering PropertyChanged on the Data property will force every data binding that starts with Data to be re-evaluated. Imagine that the Person entity has a property Family, which is a list of Person entities, and that property is data bound to a ListView. If the Data property changes, the entire ListView will be repopulated, losing any selection or scroll position, not to mention other visual artefacts such as a flicker as it redraws. Clearly this isn’t what we want to happen.

This leads us to the question of how change is managed within our application. Let’s go back over our history lesson:

- With WinForms we were required to do everything. Every change within our application we needed to evaluate whether something needed to change on the UI, and then we’d explicitly set the appropriate property on the control.

- With XAML based applications we updated properties that were data bound. We still needed to work out what changed, because we didn’t want to raise the PropertyChanged event more than was absolutely necessary.

- With React style applications we no longer need to track what’s changed, we just use the latest state to build the UI.

The latter sounds great, except for the reality is that there is going to be some change tracking going on, we just don’t need to code for it. Let’s look at an example – say we have a list of items on the screen and the user has scrolled half way down the list. If the UI was to just be rebuilt, that scroll position would be lost. The same applies to text entered into a text field etc.

Perhaps what we need to do is to abstract away the need to work out what’s changed and invoke PropertyChanged only for the properties that have actually changed – if we can do that, then updating our Data property can be done as much as it needed without worrying about weird UI artefacts……

Part 2 will show an example of how changing state can be handled in a XAML application along with using Redux to keep our state immutable

BuildIt Libraries using Continuous Delivery

Following my previous post I’ve been wondering how hard it would be to setup continuous delivery for the BuildIt libraries (a small collection of libraries that help with things like state management and some nice additions to Xamarin Forms). We already have a build process and releases configured for each library so I figured it can’t be that difficult. I’ve been tracking what the team over at ReactiveUI are doing (see https://reactiveui.net/blog/2018/05/moving-towards-vsts-and-continuous-deployment) and as I mentioned previously I think their model can work well, assuming there are enough automated tests to validate quality. In the case of the BuildIt libraries, we have some tests but not enough that I would consider it full tested, nor to the point where I would be comfortable relying on tests to ensure quality.

With this in mind, I’ve made some changes to the process for BuildIt:

- We now have two main branches:

master – This tracks what has been released to nuget as a stable release.  All changes have to be PR’d into this branch and PRs can only be created by designated individuals. PRs also have to be approved and the VSTS build has to pass

develop – this is the default branch, and tracks what’s released to nuget as a beta release (ie x.x.x-beta). All changes have to be PR’d into this branch and PRs can be created by anyone. PRs have to be approved and the VSTS build has to pass

- The VSTS build is setup as continuous integration based on either master or develop branches

- Releases are setup in VSTS pushing only to nuget (I’m considering using myget at some point too)

Alpha – Build artefacts are packaged and deployed to myget as a beta release. This is setup as continuous delivery from all branches

Beta – Build artefacts are packaged and deployed to nuget as a beta release. This is setup as continuous delivery, but has a condition that limits it to builds from the develop branch

Stable – Build artefacts are packaged and deployed to nuget as a stable release. This is setup as continuous delivery, but has a condition that limits it to builds from the master branch

The important thing for me was that anyone can submit code to create a feature or fix a bug and raise a PR on develop. The only thing in the way of a new package being released that can be tested is an approval on the PR. Limiting PRs to master limits adds a little bit of friction and allows for a bit more quality control when releasing stable builds.

Having spent a bit of this morning configuring this, I was amazed that I could effectively complete the whole process of releasing a beta and stable release of the libraries from my phone (of course I had already committed the code changes to github from my desktop).

Continuous Delivery for OSS Projects

Over the last couple of years the Microsoft/.NET developer community has had to suffer through a substantial amount of crap thanks to some rather reckless decision making by Microsoft. There’s no single culprit but hands down the single point of failure for the Microsoft community right now is Visual Studio, and this in turn is suffering due to the continual mismanagement of NuGet. In the recent builds of Visual Studio things are gradually improving but updating package references for a moderately complex project almost gives me anxiety it’s so bad – you can loose days at a time stuck in NuGet hell before you work out how to get a project back to a stable state. So what does this have to do with CD for OSS projects? Well let me explain….

Last week we had the great privilege of having Geoff Huntley hang our in the Built to Roam offices and we were sharing stories about maintaining OSS projects. One of the topics he’s passionate about is shifting ReactiveUI to a continuous delivery model. When I heard this my first comment was “you mean to beta packages, right”? His response was that, no, CD all the way through to release packages. What this would mean is that once a PR has been merged, a build will be kicked off and a new release packaged pushed out to NuGet. This isn’t a new concept and it’s one that I’ve heard being used in practice quite successfully by some business (eg Domain.com.au talk about it on their engineering blog) but applying it to an OSS project was new and immediately interesting to me.

Before we go into what needs to happen to make this happen, let’s look at why you’d want to do CD for an OSS project. After MvvmCross release v6 I raised an issue discussing release schedule and versioning and one of the points I made is that in order to boost community contributions we wanted to have a known release schedule, particularly for bug fixes. Currently the goal is that if you submit a bug fix via a PR, it should be available in the next patch release, which should go out at the beginning of each month. But what if you only had to wait for your bug fix to be approved and merged – imagine if that then triggered a build and release of a new NuGet package that you could pull into your application. My belief is that this would significantly increase the willingness of the community to contribute and build a more collaborative ecosystem.

Here’s the kicker – what needs to happen in order to do CD? The answer is basically the same as any release process – you need to ensure the release meets your quality bar (however you chose to measure that). Currently for MvvmCross we have a minimal set of unit tests that are run as part of a build. Beyond that, we rely on the maintainers having a good sense of the stability of the framework – this in itself is pretty concerning but unfortunately all too common. The difficulty with a project such as MvvmCross is the sheer matrix of different platforms it supports (eg iOS, Android, UWP, Xamarin Forms (iOS, Android, UWP…..), WPF, MacOS…) and having to write unit and integration tests for all of them, and then be able to run each of the tests on real devices. There are solutions out there, such as App Center Test, which allows for tests to be run on real devices, but what do we do for platforms such as Tizen which aren’t in the list of supported test devices?

So back to my introductory comments – let’s assume that we can solve the CD quality bar issue and that we’re pushing out new packages each time a PR is approved. Now let’s also assume that every package author is setup to do the same, what does that mean for the application I’m building – am I going to be suffering a heart attack every week from the continual need to upgrade package references?

One suggestion is to let Visual Studio start to do the heavy lifting for you – set you packagereferences to use Version=”*” for all packages – this will use the latest stable package and will upgrade as and when they change. Of course, there will be scenarios where you may need to intervene and set specific package versions (eg where there are incompatibilities between different package versions).

To go along with this suggestions is a massive word of caution – whilst in theory this should work well, as we move to a model where more packages are releasing more frequently, Visual Studio will need to keep pace. I don’t believe the current NuGet infrastructure within Visual Studio could handle CD for all package references (and that’s assuming NuGet itself could handle it!!!). Let’s hope that Microsoft are onto this already and have some massive improvements in the pipeline.

Update 6th May: Unfortunately it appears that I was premature in suggesting that we can set the Version in packagereference to *, specifically for cross platform development. Whilst it does appear to work for .NET Standard libraries, it does not work for legacy project types such as Xamarin Android, Xamarin iOS and UWP. Until these project types are updated to handle * versioning, you’re going to have to continue to fix the version referencing.

MVX+1 Update

MvvmCross v6.0.1 was recently released. I’ve just updated both FirstDemo and TipCalc to reference v6.0.1 of MvvmCross

One of the changes that I did make to all projects is how packages are referenced. By default in Visual Studio when you reference a NuGet package it will draw in the specific version. However, by editing the csproj you can set the version to * which will mean Visual Studio will draw in the latest stable version of your referenced libraries. This is particularly convenient if you’re not in the habit of remembering to upgrade packages frequently. The downside is that you may discover one day that your app stops working, or behaves differently, thanks to a new package version being used by your application. More on this in a future post once I’ve collected my current thinking regarding continous deployment and the impact this would have on app development

MVX=0 WPF/Mac: A first MvvmCross Application (MVX+1 days of MvvmCross)

Further to some feedback on the first couple of posts in the MVX+1 series (MVX=0, MVX=0F and MVX=1), I’ve gone back and added WPF and Mac support to the FirstDemo to show just how powerful MvvmCross is. I’ll cover very briefly here how to add these project types and then I’ll be updating the TipCalc post to include the basics for WPF and Mac setup in there too.

Let’s start with WPF:

  1. Add a WPF App (.NET Framework) called FirstDemo.Wpf
    image
  2. Add a reference to MvvmCross NuGet package
  3. Add reference to FirstDemo.Core project
  4. Add ProxyMvxApplication to App.xaml.cs
    public abstract class ProxyMvxApplication : MvxApplication<MvxWpfSetup<Core.App>, Core.App> { }
  5. Update App class in both App.xaml and App.xaml.cs to inherit from ProxyMvxApplication
  6. Remove all code in the App class (in App.xaml.cs) except for the constructor with call to InitializeComponent
    public App()
    {
         InitializeComponent();
    }
  7. Update MainWindow in both MainWindow.xaml and MainWindow.xaml.cs to inherit from MvxWindow
  8. Create Views folder
  9. Add new User Control (WPF) called FirstView.xaml
  10. Update FirstView in both FirstView.xaml and FirstView.xaml.cs to inherit from MvxWpfView
  11. Add XAML to FirstView.xaml
    <StackPanel Margin="12,12,12,12">
         <TextBox Text="{Binding FirstName, Mode=TwoWay}"></TextBox>
         <TextBox Text="{Binding LastName, Mode=TwoWay}"></TextBox>
         <TextBlock Text="{Binding FullName}"></TextBlock>
    </StackPanel>

You should now be able to build and run the WPF application – notice how little code we have to add/change in order to get MvvmCross to work!

Next up is Mac which at the moment can only be done on a Mac (almost no surprises there – it’s the same as not being able to do UWP development on a Mac I guess):

  1. Add a Cocoa App called FirstDemo.Mac
    image
  2. Add a reference to MvvmCross NuGet package
  3. Add reference to FirstDemo.Core project
  4. At this point I would recommend unloading your project, editing the csproj file manually to removed the legacy nuget reference and add the following ItemGroup. Also remove the reference to package.config, remove the actual package.config file and delete both bin and obj folders. Reload the Mac project and force a rebuild.
    <ItemGroup>
       <PackageReference Include="MvvmCross" Version="6.0.0" />
    </ItemGroup>
  5. Update AppDelegate to inherit from MvxApplicationDelegate
    [Register("AppDelegate")]
    public class AppDelegate: MvxApplicationDelegate<MvxMacSetup<App>, App>
    {
         public override void DidFinishLaunching(NSNotification notification)
         {
             MvxMacSetupSingleton.EnsureSingletonAvailable(this, MainWindow).EnsureInitialized();
             RunAppStart();
            // Due to a bug, do not call base DidFinishLaunching
             //base.DidFinishLaunching(notification);
         }
    }
    Note: There is a bug at the moment where if you don’t override DidFinishLaunching the application will crash on startup
  6. Open main.storyboard – this should open the storyboard in the XCode designer
  7. Select the existing view controller and set the Class and Storyboard ID to FirstView
    image
  8. Make sure the FirstView name change has been saved; return to VS for Mac and confirm that files FirstView.cs and FirstView.designer.cs have been created. If these have not been created, I would suggest doing a rebuild of your project to make sure the changes to the storyboard have been processed and the appropriate designer files created.
  9. From the Object Library drag two TextField and a Label across onto the design surface
    image
  10. Open Project navigator and make sure you have FirstView.h and FirstView.m. If you don’t I would suggest closing both XCode and VS for Mac, deleting the bin and obj folder from within the FirstDemo.Mac folder and reopening the solution in VS for Mac. Rebuild the Mac project and then launch XCode by double clicking on main.storyboard.
    image
  11. Hide both Project navigator (left pane) and Utilities (right pane) and show the Assistant Editor (the icon button that has linked circles in top right corner of XCode)
  12. From the navigator bar in the Assistant Editor, select Manual –> FirstView.Mac –> FirstView.h
    image
  13. Right-click on the first TextField
    image
  14. Click and drag the circle next to New Referencing Outlet across onto the FirstView.h immediately before the @End. When you release, you should be prompted to complete information about the new Outlet where you can specify the Name, textEditFirst, which will be the name of the backing variable you’ll be able to use to reference the TextField in code
    image
  15. Repeat the previous step for the second TextField, textEditSecond, and the Label, labelFull.
  16. Update FirstView.cs to add the MvxFromStoryboard attribute, change the base class to MvxViewController and add data binding using the CreateBindingSet extension
    [MvxFromStoryboard("Main")]
    public partial class FirstView : MvxViewController<FirstViewModel>
    {
         public FirstView(IntPtr handle) : base(handle)
         {
         }
  17.     public override void ViewDidLoad()
         {
             base.ViewDidLoad();
             var set = this.CreateBindingSet<FirstView, FirstViewModel>();
             set.Bind(textEditFirst).To(vm => vm.FirstName);
             set.Bind(textEditSecond).To(vm => vm.LastName);
             set.Bind(labelFull).To(vm => vm.FullName);
             set.Apply();
         }
    }

And there you have it – build and run your Mac FirstDemo application

    MvvmCross: Initialize method on the first view model

    An issue was raised on MvvmCross following the release of v6 where applications were breaking because they have async code in the Initialize method of the first view model. Changes in v6 mean that the first view model is effectively loaded synchronously. This change was made because applications should not do heavy lifting before displaying the first view of their application as there are platform requirements that will cause the application to terminate if it doesn’t display the first view within the appropriate time window. This change means that any code that attempts to jump to a different thread (even something like Task.Delay) will cause the fist view of the application to break.

    In some scenarios this doesn’t make sense – for example if you have a splash screen Activity on Android, the first navigation can be done asynchronously because you already have a view being displayed on the screen. Here I’m going to use a simple example to demonstrate how to resolve this issue – you should only use this if you are using a splash screen for the first view of your application.

    Let’s start by breaking our application by adding the following to our first view model:

    public override async Task Initialize()
    {
         await Task.Delay(2000);
         await base.Initialize();
    }

    If you make this change and attempt to run your application you’ll see a black screen (on Android – and I’m using Android because we typically have a splash Activity such as in my earlier post).

    Next we’re going to fix this by overriding the MvxAppStart class to make the first navigation asynchronous:

    public class CustomMvxAppStart<TViewModel> : MvxAppStart<TViewModel>
         where TViewModel : IMvxViewModel
    {
         public CustomMvxAppStart(IMvxApplication application, IMvxNavigationService navigationService) : base(application, navigationService)
         {
         }

        protected override void NavigateToFirstViewModel(object hint)
         {
             NavigationService.Navigate<TViewModel>();
         }
    }

    Note that it’s the bold line that we’ve changed from the built in MvxAppStart class where we call NavigationService.Navigate<TViewModel>().GetAwaiter().GetResult(); which forces the navigation to be done synchronously.

    We now need to make sure that our CustomMvxAppStart is used. To do this we just need to change a single line in the App.cs to use RegisterCustomAppStart instead of RegisterAppStart

    RegisterCustomAppStart<CustomMvxAppStart<FirstViewModel>>();

    And we’re done – running the application now will allow the application to load successfully.

    MVX=1: TipCalc - a second example - adding IoC and the Xamarin Android Designer (MVX+1 days of MvvmCross)

    Following on from the first post in the MVX+1 series, in this post we’ll create a basic Tip Calculator (mirroring the original post from the N+1 series). However, in this case the first section is a more detailed set of instructions on how to get the basics of all three platforms setup with MvvmCross. Going forward we’ll use this as a starting point so that we don’t need to cover over this in each subsequent post.

    Source code: https://github.com/nickrandolph/MvxPlus1DaysOfMvvmCross/tree/master/Mvx-01-TipCalc

    Getting Started Instructions (Native Apps)

    Note: In this case the name of the application is TipCalc but these instructions can be followed to get any new project started by simply replacing TipCalc with the name of your project.

    1. Create a the new solution by creating a new Class Library (.NET Standard) with the project name set to TipCalc.Core and the solution name to just TipCalc.
    2. Add a new project based on the Blank App (Universal Windows) project template called TipCalc.Uwp (make sure that the Minimum and Target versions are set to at least the Fall Creators Update)
    3. Add a new project based on the Android App (Xamarin) project template called TipCalc.Droid (use the Blank app template)
    4. Add a new project based on the iOS App (Xamarin) project template called TipCalc.iOS (use the Blank app template)
    5. Add a reference to MvvmCross NuGet package (v6.0.0 at time of writing to all four projects)
    6. TipCalc.Uwp: Update NuGet package Microsoft.NETCore.UniversalWindowsPlatform to the latest stable version (6.0.8 at time of writing)
    7. TipCalc.Droid: Update the Android version to Use Latest Platform (Project Properties –> Application –> Target Framework)
    8. TipCalc.Droid: Update Xamarin.Android.Support.Design to latest stable version (27.0.2 at time of writing)
    9. TipCalc.Droid: Add a reference to MvvmCross.Droid.Support.V7.AppCompat package
    10. TipCalc.iOS: Unload project; delete packages.config; edit TipCalc.iOS.csproj and add the following ItemGroup
      <ItemGroup>
         <PackageReference Include="MvvmCross" Version="6.0.0" />
      </ItemGroup>
    11. Add a reference to TipCalc.Core to each of the three head projects (ie TipCalc.Uwp, TipCalc.Droid and TipCalc.iOS)
    12. TipCalc.Core: Rename the default Class1.cs to App.cs, and allow Visual Studio to rename class to App
    13. TipCalc.Core: Change the App class to inherit from MvxApplication
    14. TipCalc.Core: Add a folder, ViewModels, and add a class called FirstViewModel.
    15. TipCalc.Core: Change FirstViewModel to inherit from MvxViewModel
    16. TipCalc.Core: Override Initialize method in App to register services and set startup view model to FirstViewModel
      public override void Initialize()
      {
           CreatableTypes()
                   .EndingWith("Service")
                   .AsInterfaces()
                   .RegisterAsLazySingleton();
           RegisterAppStart<FirstViewModel>();
      }
    17. TipCalc.Uwp: Add a help class ProxyMvxApplication
      public abstract class ProxyMvxApplication: MvxApplication<MvxWindowsSetup<Core.App>, Core.App> { }
    18. TipCalc.Uwp: Change App.xaml and App.xaml.cs to inherit from ProxyMvxApplication
    19. TipCalc.Uwp: Remove all code in App.xaml.cs other than the constructor which should contain a single call to InitializeComponent
    20. TipCalc.Uwp: Delete MainPage.xaml and MainPage.xaml.cs
    21. TipCalc.Uwp: Add a Views folder, and  add a FirstView based on the Blank Page template
    22. TipCalc.Uwp: Change FirstView.xaml and FirstView.xaml.cs to inherit from MvxWindowsPage
    23. TipCalc.Droid: Add a new class, MainApplication, that inherits from MvxAppCompatApplication
    24. [Application]
      public class MainApplication : MvxAppCompatApplication<MvxAppCompatSetup<App>, App>
      {
           public MainApplication(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
           {
           }
      }

    25. TipCalc.Droid: Rename MainActivity.cs to SplashScreen.cs and let Visual Studio rename the class
    26. TipCalc.Droid: Rename activity_main.axml to SplashScreen.axml, and adjust layout to indicate application loading
    27. TipCalc.Droid: Adjust SplashScreen class to inherit from MvxSplashScreenAppCompatActivity and set NoHistory to true (since we don’t want the user to be able to press the back button and go back to the splash screen)

      [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true, NoHistory = true)]
      public class SplashScreen : MvxSplashScreenAppCompatActivity

    28. TipCalc.Droid: Add a folder, Views, and add a new Activity, FirstView.c
    29. [Activity(Label = "FirstView")]
      public class FirstView : MvxAppCompatActivity<FirstViewModel>
      {
           protected override void OnCreate(Bundle bundle)
           {
               base.OnCreate(bundle);

              SetContentView(Resource.Layout.FirstView);
           }
      }

    30. TipCalc.Droid: Add a new Android Layout to the Resources/Layout folder, FirstView.axml
    31. TipCalc.Droid: You may run into an error: “error XA4210: You need to add a reference to Mono.Android.Export.dll when you use ExportAttribute or ExportFieldAttribute.” If you do, you just need to Add Reference to Mono.Android.Export (search in the Add Reference dialog).
    32. TipCalc.iOS: Update AppDelegate class to inherit from MvxApplicationDelegate, and remove the default code.
      [Register("AppDelegate")]
      public class AppDelegate : MvxApplicationDelegate<MvxIosSetup<App>, App>
      {
      }
    33. TipCalc.iOS: Add an Empty Storyboard, called Main.storyboard, to the root of the project
    34. TipCalc.iOS: Add a ViewController to the Main.storyboard using the designer and set the Class and Storyboard ID to FirstView (also make sure the “User Storyboard ID” checkbox is set to true)
    35. TipCalc.iOS: Move the generated FirstView.cs and FirstView.designer.cs files (from the previous step) into a new folder called Views, and adjust the namespace of the FirstView class to FirstView.iOS.Views
    36. TipCalc.iOS: Update the FirstView class to inherit from MvxViewController
      [MvxFromStoryboard("Main")]
      public partial class FirstView : MvxViewController<FirstViewModel>


    Now to actually build out the Tip Calculator. Rather than embed the calculation logic into our view model, we’re going to abstract it out into a service. To do this we’ll make use of the IoC container made available by MvvmCross. We’ll register a CalculationService which will be injected into our view model constructor.

    Let’s continue our development of the Tip Calculator in TipCalc.Core:

    1. Add a folder called Services
    2. Add an interface ICalculationService into the Services folder
      public interface ICalculationService
      {
           double Tip(double subTotal, double generosity);
      }
    3. Add a class, CalculationService, which implements ICalculationService, again into the Services folder
      public class CalculationService : ICalculationService
      {
           public double Tip(double subTotal, double generosity)
           {
               return subTotal * generosity / 100.0;
           }
      }

    4. Add a constructor to the FirstViewModel which accepts an ICalculationService parameter
    5. private readonly ICalculationService _calculationService;
      public FirstViewModel(ICalculationService calculationService)
      {
           _calculationService = calculationService;
      }

    6. Add properties for SubTotal, Generosity, Tip and Total. Each property should take the following form where SetProperty is called within the setter
      private double _subTotal;
      public double SubTotal
      {
           get { return _subTotal; }
           set { SetProperty(ref _subTotal, value); }
      }
    7. Add a Recalc method which will invoke the Tip method on the ICalculationService
      private void Recalc()
      {
           Tip = _calculationService.Tip(SubTotal, Generosity);
           Total = SubTotal + Tip;
      }
    8. Add a call to Recalc into the setter for both SubTotal and Generosity
    9. Set some initial values for the SubTotal and Generosity (if you use the property setters, rather than setting the fields, the Recalc method will be invoked)

    That’s it for the core logic for the application. Now we just need to wire up the UI for each platform.

    One thing that’s worth noting is that in step 16 of the original setup where the Initialize method is overridden, there is logic in the Initialize method to interrogate the current assembly looking for all classes that end in Service and register them, based on their interface, with the MvvmCross IoC container – this is how MvvmCross knows about the implementation of the ICalculationService which is used when instantiating the FirstViewModel.

    Let’s built out the UWP interface in TipCalc.Uwp:

    1. Add the following XAML inside the existing Grid element:
      <StackPanel>
           <TextBlock Text="SubTotal"/>
           <TextBox Text="{Binding SubTotal, Mode=TwoWay}"/>
           <TextBlock Text="How generous?"/>
           <Slider Value="{Binding Generosity, Mode=TwoWay}"
                   Minimum="0"
                   Maximum="100"/>
           <TextBlock Text="Tip:"/>
           <TextBlock Text="{Binding Tip}"/>
           <TextBlock Text="SubTotal:"/>
           <TextBlock Text="{Binding Total}"/>
      </StackPanel>

    That’s the UWP interface done – four elements (with TextBlock headings): TextBox and Slider for inputting SubTotal and Generosity using two-way data binding, and two TextBlock for outputting the Tip and Total amounts.

    Now let’s do Android:

    1. Add the following namespace declaration to FirstView.axml
      xmlns:local="http://schemas.android.com/apk/res-auto"
    2. Add the following xml to FirstView.axml
      <TextView
           android:text="SubTotal"
           android:textAppearance="?android:attr/textAppearanceMedium"
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           android:id="@+id/textView1" />
      <EditText
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           android:id="@+id/editText1"
           local:MvxBind="Text SubTotal" />
      <TextView
           android:text="Generosity"
           android:textAppearance="?android:attr/textAppearanceMedium"
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           android:id="@+id/textView2" />
      <SeekBar
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           local:MvxBind="Progress Generosity"
           android:id="@+id/seekBar1" />
      <TextView
           android:text="Tip"
           android:textAppearance="?android:attr/textAppearanceMedium"
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           android:id="@+id/textView3" />
      <TextView
           android:textAppearance="?android:attr/textAppearanceMedium"
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           local:MvxBind="Text Tip"
           android:id="@+id/textView4" />
      <TextView
           android:text="Total"
           android:textAppearance="?android:attr/textAppearanceMedium"
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           android:id="@+id/textView5" />
      <TextView
           android:textAppearance="?android:attr/textAppearanceMedium"
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           local:MvxBind="Text Total"
           android:id="@+id/textView6" />

    In this case we’re leveraging the xml extensions offered by MvvmCross in order to do the data binding using the MvxBind syntax.

    Finally, let’s do iOS:

    1. Add the following code to the FirstView.cs
      public override void ViewDidLoad()
      {
           base.ViewDidLoad();
    2.     // Perform any additional setup after loading the view
           var label = new UILabel(new RectangleF(10, 0, 300, 40));
           label.Text = "SubTotal";
           Add(label);

          var subTotalTextField = new UITextField(new RectangleF(10, 40, 300, 40));
           Add(subTotalTextField);

          var label2 = new UILabel(new RectangleF(10, 80, 300, 40));
           label2.Text = "Generosity?";
           Add(label2);

          var slider = new UISlider(new RectangleF(10, 120, 300, 40));
           slider.MinValue = 0;
           slider.MaxValue = 100;
           Add(slider);

          var label3 = new UILabel(new RectangleF(10, 160, 300, 40));
           label3.Text = "Tip";
           Add(label3);

          var tipLabel = new UILabel(new RectangleF(10, 200, 300, 40));
           Add(tipLabel);

          var label4 = new UILabel(new RectangleF(10, 240, 300, 40));
           label4.Text = "Total";
           Add(label4);

          var totalLabel = new UILabel(new RectangleF(10, 280, 300, 40));
           Add(totalLabel);

         var set = this.CreateBindingSet<FirstView, FirstViewModel>();
           set.Bind(subTotalTextField).To(vm => vm.SubTotal);
           set.Bind(slider).To(vm => vm.Generosity);
           set.Bind(tipLabel).To(vm => vm.Tip);
           set.Bind(totalLabel).To(vm => vm.Total);
           set.Apply();

      }

    In this case for iOS we again make use of the data binding support provided by MvvmCross by using the CreateBindingSet method, followed by a call to Bind for each element property we want to bind, and then finally a call to Apply to complete the setup of data binding.

    And that’s it – a Tip Calculator for all three platforms.

    MVX=0F Side Note: Adding a Splash Screen

    I received some feedback on my previous post on setting up MvvmCross for Xamarin.Forms, asking how to add a splash screen to the Android Forms application. In the post MVX=0 I converted the MainActivity that comes as part of the standard Xamarin Android project into a SplashScreen but when it came to the Android project for Xamarin.Forms I left it without a splash screen.

    Luckily adding a splash screen is really easy, so let’s add one to the Forms.Droid project:

    1. Copy the SplashScreen.axml from the /Resources/layout folder in the FirstDemo.Droid project into the /Resources/layout folder in the Forms.Droid project
    2. Remove “MainLauncher = true” from the Activity attribute on the MainActivity
    3. Change the MainActivity inheritance:
      public class MainActivity : MvxFormsAppCompatActivity<MainViewModel>
    4. Add a new class, SplashScreen.cs:
      [Activity(Label = "FirstDemo.Forms.Splash", Theme = "@style/MainTheme", MainLauncher = true, NoHistory = true)]
      public class SplashScreen : MvxFormsSplashScreenAppCompatActivity<MvxFormsAndroidSetup<Core.App, App>, Core.App, App>
      {
           public SplashScreen() : base(Resource.Layout.SplashScreen)
           {
           }
    5.     protected override void RunAppStart(Bundle bundle)
           {
               StartActivity(typeof(MainActivity));
               base.RunAppStart(bundle);
           }
      }

    And there you have it – the Android Xamarin.Forms project will launch with a splash screen before redirecting to the MainActivity which will host the Xamarin.Forms content.

    Declarative C# as an alternative to XAML

    Yesterday I had one of those moment where one minute you’re super opinionated on something, only for someone to point out how things have changed and that you should re-evaluate your position – As much as I have my personal preferences on a lot of developer related topics, I try to listen to those around me and look at why they’re doing things their way, and whether I can adapt/learn/extend what I’m doing.

    Yesterday in my post talking about CSS in Xamarin.Forms I made a comment that developers building for Xamarin.Forms should be using XAML and “if you’re doing it in code, you’re wasting everyone’s time”. Almost immediately after posting this I was following a related twitter thread (Adam’s thread on whether XAML is holding Xamarin.Forms back) and I saw a link to the work that Vincent has been doing on using declarative c# instead of XAML. This started with a discussion on the Xamarin forums: https://forums.xamarin.com/discussion/123771/using-declarative-style-c-instead-of-xaml-should-xamarin-redirect-xaml-efforts-elsewhere? Then Vincent provided a link to his repo on Github: https://github.com/VincentH-Net/CSharpForMarkup

    My issue with using C# to define layout is that out of the box it’s very difficult to construct layouts without it making it look like a jumbled mess – XAML makes the layout very clean and easy for any XAML developer to easily grok what’s going on. However, what Vincent has done is provide some simple extensions that make it possible to define the layout in a very fluent manner.

    Whilst I still prefer, and would recommend using XAML, if you must use C# to define layouts, you should look at the work Vincent has done and perhaps leverage it in your code. Furthermore I’d love to see some metrics on whether there is a noticeable performance gain in using C# versus compiled XAML, and how to handle styles, templates and other resources in code.

    Xamarin Forms gets CSS to pander to web developers

    I just finished reading a good post by fellow Microsoft MVP, Sam Basu, looking at how to use CSS for styling web development. Since becoming aware of the intent to add CSS as a styling option with Xamarin Forms I’ve been an advocate against it, not because I’m “not a web guy” but because the platform doesn’t need options. Xamarin Forms is a great platform and one that I’ve been talking, blogging and working with since it was created; it’s not perfect but it’s incredibly powerful in how quickly cross-platform applications can be generated. What it does not need is a second alternative for styling.

    In talking with the product team and other Xamarin Forms developers I’m always keen to understand their opinions, so I decided that I’d review Sam’s list of CSS benefits and try to boil them down into why I think the decision was made to add CSS. My summary of the list it comes down to (I’ve discounted the other comments because they’re just statements, not really benefits of CSS over XAML styling):

    - The developer ecosystem is inundated with web developers (ie people who know and understand CSS) so let’s give them a technology they’re familiar with (without having to learn anything new)

    - CSS is less verbose

    - CSS offers additional styling inheritance

    -  CSS can be shared between web and Xamarin Forms applications

    Let me leave the first point for a second – I promise I’ll come back to it. The second point regarding CSS being less verbose is a bit irrelevant since intellisense/autocomplete makes writing XAML styles super quick; XAML styles are then compiled and so don’t need to be parsed in the way CSS does. I have to admit, one of the only benefits I see of using CSS is around styling inheritance and referencing – this has always been a limitation of XAML styles and one that I would love to see a fix for, rather than cobbling some other styling alternative. The last point regarding sharing CSS between web and Forms might be nice in theory but as we’ve seen say across Phone, Windows, Xbox, the reality is that most of the styling needs to be adjusted per platform anyhow, so the benefits are marginal at best.

    The article goes on to talk about some caveats – I’ll rephrase this as “Here are the reasons you should never use CSS in you Xamarin Forms application”:

    - XAML styling is, and I’m guessing, will continue to be the primary way to do styling in Xamarin Forms – anything else will be built on top of this meaning that all new features will come later, if at all, to CSS

    - There are some limitations on what CSS can do, even today – do you think this will get addressed any time soon? I wouldn’t be betting the future of any project on these getting addressed in the short term, if ever.

    - CSS is parsed – Xamarin/Xamarin Forms adds enough overhead as it is, do you really want to slow down your mobile apps further. Just on this note, please make sure you optimise your apps, leveraging XAML compilation

    Ok so I mentioned I’d come back to the first benefit of using CSS which is that it’s a familiar technology for web developers – the reality is that Xamarin.Forms is for building mobile applications and unless you’ve come from a background of building SPAs with offline capabilities (such as building a PWA), chances are you’re going to need to learn a bunch more than just XAML syntax. Furthermore, if you’re going to be building with Xamarin.Forms you need to be using XAML to layout your pages (if you’re doing it in code, you’re wasting everyone’s time), so why wouldn’t you use XAML styling too.

    Now, do I think that XAML styling is perfect? – it is definitely not. The lack of even simple things like multiple inheritance, and in the case of Xamarin.Forms, basic control templates for the standard controls, are annoyances and need to be fixed. I think there is an opportunity to learn from CSS and adapt it to improve XAML across the board. Do I think this is a good enough reason for adding CSS? NO, I repeat NO – you can’t imagine the resource drain that CSS will have on the Xamarin.Forms product team (bugs, feature requests, support for new features).

    Going forward I’d like Xamarin.Forms to focus on core requirements with a view to “bringing back the magic”.

    MVX=0F: A first MvvmCross Application (MVX+1 days of MvvmCross)

    Updated 16/4/2018: Reference to MvvmCross have been updated to v6.0.0

    One of the awesome things about MvvmCross is that you can take the exact same set of ViewModels that you used for your UWP, iOS, Android applications and use them in a Xamarin Forms application. As we go through the MVX+1 series, I’ll make some space for talking about Xamarin Forms as well.

    In this post we're going to extent what we started in the previous post by adding a Xamarin Forms interface – this means creating new head projects for iOS, Android and UWP too. All up we’re adding four new projects but fear not, most of the heavy lifting is done by Visual Studio:

    Into our existing solution we’re going to add a new Xamarin Forms project:

    1. Add a new Mobile App (Xamarin.Forms) project called FirstDemo.Forms
      image_thumb1_thumb
    2. When prompted, select Blank App, make sure all three Platforms are checked and make sure you select the .NET Standard option (Do NOT use the Share Project option).
      image_thumb3_thumb
    3. Upgrade the Xamarin.Forms NuGet to latest for all four Forms projects (at time of writing is 2.5.1.444934)
    4. Add MvvmCross NuGet Package to all Forms projects (Forms, Forms.iOS, Forms.Android and Forms.UWP)
    5. Add MvvmCross.Forms NuGet Package to all Forms projects (Forms, Forms.iOS, Forms.Android and Forms.UWP)

    Note: You may need to upgrade to latest NuGet packages for all Forms projects before you can add references to the MvvmCross packages.

    Update the FirstDemo.Forms project

    1. Remove all code in App class except for constructor with a call to InitializeComponent
    2. Create Views folder
    3. Move MainPage into Views folder and rename to FirstView
    4. Adjust FirstView.xaml and FirstView.xaml.cs to change class name to FirstView and to make it inherit from MvxContentPage
    5. Add two Entry and a Label with data binding to FirstView.xaml


    Update the FirstDemo.Forms.Uwp project

    1. Update Microsoft.NETCore.UniversalWindowsPlatform (v6.0.8 at time of writing)
    2. Add reference to FirstDemo.Core
    3. Change MainPage to inherit from MvxFormsWindowsPage
    4. Remove all code other than the InitializeComponent method call in the constructor of MainPage
    5. Add ProxyMvxApplication
      public abstract class ProxyMvxApplication : MvxWindowsApplication<MvxFormsWindowsSetup<Core.App, FirstDemo.Forms.App>, Core.App, FirstDemo.Forms.App, MainPage>
    6. Change App.xaml and App.xaml.cs to inherit from ProxyMvxApplication
    7. Remove all code other than the constructor, with a single call to InitializeComponent, in App.xaml.cs

    Update the FirstDemo.Forms.Android project

    Note (1): If you run into the following error, you may need to rename your project. In this case we renamed it to Forms.Droid (as well as the folder the project resides in)
    1>C:\Program Files (x86)\Microsoft Visual Studio\Preview\Enterprise\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(2088,3): error MSB4018: System.IO.PathTooLongException: The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.

    Note (2): If you’re using the preview build of Visual Studio, you may run into an error: “error XA4210: You need to add a reference to Mono.Android.Export.dll when you use ExportAttribute or ExportFieldAttribute.” If you do, you just need to Add Reference to Mono.Android.Export (search in the Add Reference dialog).

    1. Change Forms.Android project to target latest Android SDK (v8.1 at time of writing)
    2. Upgrade Xamarin.Android.Support.* to latest for the Forms.Android project
    3. Add reference to FirstDemo.Core
    4. Add an additional class, MainViewModel, to FirstDemo.Core that inherits from MvxViewModel [NB: This is required at the moment because of a bug in the current beta]
      5. Add custom setup class [NB: This is required because of a bug in the current beta]
      public class CustomSetup : MvxFormsAndroidSetup<Core.App, FirstDemo.Forms.App> { }
    5. Change MainActivity inheritance, remove code except for a constructor:
      public class MainActivity : MvxFormsAppCompatActivity<MvxFormsAndroidSetup<Core.App, App>, Core.App, App, MainViewModel>
      {
      }

    Update the FirstDemo.Forms.iOS project

    1. Add reference to FirstDemo.Core
    2. Changed inheritance of AppDelegate
      public class AppDelegate : MvxApplicationDelegate<MvxIosSetup<App>, App>

    And there you have it – you should be able to build and run all three Forms projects utilising the same view models that the non-Forms projects used.

    MVX=0 : A first MvvmCross Application (MVX+1 days of MvvmCross)

    [Repost: Apologies for those who have already read this but there were some issues with the link generated for the previous post, so I’ve reposted it]

    Updated 16/4/2018: Reference to MvvmCross have been updated to v6.0.0

    Yes, this is going to be a sequence of posts reworking the infamous N+1 series that Stuart Lodge did starting almost exactly 5 years ago. As we approach the 5 year anniversary of these posts I thought it only fitting to cover this series again as a way of introducing MvvmCross v6 which will be released very shortly has just been released. Unlike the original series that were YouTube videos accompanied by blog posts, this series will only contain the posts, mainly because I find generating videos to be time consuming. Anyhow, here goes:

    We’ll start by creating a Blank Solution.

    image_thumb4_thumb

    Into the solution we’ll add a Core Library that will contain an App class and our first ViewModel:

    1. Add a Class Library (.NET Standard) called FirstDemo.Core
      image_thumb3_thumb
    2. Add a reference to MvvmCross NuGet package (v6.0.0-beta.8 v6.0.0 at time of writing)
    3. Rename the default Class1.cs to App.cs, and allow Visual Studio to rename class to App
    4. Change App to inherit from MvxApplication
    5. Add a folder, ViewModels, and add a class called FirstViewModel.
    6. Change FirstViewModel to inherit from MvxViewModel
    7. Add logic to FirstViewModel to include FirstName, LastName and a calculated FullName
    8. Override Initialize method in App to call RegisterAppStart, specifying FirstViewModel as the startup ViewModel

    Let’s start with a Universal Windows Platform UI:

    1. Add a Blank App (Universal Windows) called FirstDemo.Uwp
      image_thumb6_thumb
    2. Make sure Minimum and Target versions are set to at least the Fall Creators Update so that it supports .NET Standard 2.0
      image_thumb8_thumb
    3. Update NuGet package Microsoft.NETCore.UniversalWindowsPlatform to the latest stable version (6.0.8 at time of writing)
    4. Add a reference to MvvmCross NuGet package
    5. Add reference to FirstDemo.Core project
    6. Add a help class ProxyMvxApplication to the FirstDemo.Uwp project – this is a proxy class to compensate for the lack of generics support in XAML
    7. public abstract class ProxyMvxApplication: MvxApplication<MvxWindowsSetup<Core.App>, Core.App> { }

    8. Change App.xaml and App.xaml.cs to inherit from ProxyMvxApplication
    9. Remove all code in App.xaml.cs other than the constructor which should contain a single call to InitializeComponent
    10. Delete MainPage.xaml and MainPage.xaml.cs
    11. Add a Views folder, and  add a FirstView based on the Blank XAML page template
    12. Change FirstView.xaml and FirstView.xaml.cs to inherit from MvxWindowsPage
    13. Add some TextBoxes and a TextBlock to the FirstView, complete with databinding
    14. Hit F5 and run the application (you may have to set the FirstDemo.Uwp project as the startup project and make sure it’s set to build and deploy using the Configuration Manager)

    Next let’s add the Android UI:

    1. Add a Android App (Xamarin) called FirstDemo.Droid
      image_thumb10_thumb
    2. Select the Blank App template, and the minimum Android version
    3. Update the Xamarin.Android.Support.Design NuGet package (at time of writing the latest is 27.0.2)
    4. Update the Android version to Use Latest Platform
      image_thumb12_thumb
    5. Add a reference to MvvmCross NuGet package
    6. Add a reference to MvvmCross.Droid.Support.V7.AppCompat package
    7. Add reference to FirstDemo.Core project
    8. Add a new class, MainApplication, that inherits from MvxAppCompatApplication
      public class MainApplication : MvxAppCompatApplication<MvxAppCompatSetup<App>, App>
    9. Rename MainActivity.cs to SplashScreen.cs and let Visual Studio rename the class
    10. Rename activity_main.axml to SplashScreen.axml, and adjust layout to indicate application loading
    11. Adjust SplashScreen class to inherit from MvxSplashScreenAppCompatActivity and set NoHistory to true (since we don’t want the user to be able to press the back button and go back to the splash screen)
    12. [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true, NoHistory = true)]
      public class SplashScreen : MvxSplashScreenAppCompatActivity

    13. Add a folder, Views, and add a new Activity, FirstView.cs
      1. Add a new Android Layout to the Resources/Layout folder, FirstView.axml, with a couple of EditText and a TextView, all data bound using MvxBind
      2. You may run into an error: “error XA4210: You need to add a reference to Mono.Android.Export.dll when you use ExportAttribute or ExportFieldAttribute.” If you do, you just need to Add Reference to Mono.Android.Export (search in the Add Reference dialog).
      3. Set the startup project to be FirstDemo.Droid and press F5 to run the application

      Lastly, let’s add the iOS UI:

      1. Add an iOS App (Xamarin) called FirstDemo.iOS
        image_thumb2_thumb
      2. Select the Blank App template, Universal devices support and Minimum iOS Version of 11.2
        1. Add a reference to MvvmCross NuGet package
          1. Add reference to FirstDemo.Core project
          2. Update AppDelegate class to inherit from MvxApplicationDelegate
            public class AppDelegate : MvxApplicationDelegate<MvxIosSetup<App>, App>
          3. Add an Empty Storyboard, called Main.storyboard, to the root of the project
          4. Add a ViewController to the Main.storyboard using the designer and set the Class and Storyboard ID to FirstView (also make sure the “User Storyboard ID” checkbox is set to true)
          5. Move the generated FirstView.cs and FirstView.designer.cs files (from the previous step) into a new folder called Views, and adjust the namespace of the FirstView class to FirstView.iOS.Views
          6. Add two UITextField and a UILabel to the FirstView ViewController using the Main.storyboard designer (make sure each element has a Name set so it can be referenced from code)
          7. Update the FirstView class to inherit from MvxViewController
            [MvxFromStoryboard("Main")]
            public partial class FirstView : MvxViewController<FirstViewModel>
          8. Add logic to FirstView to enable databinding using the CreateBindingSet extension method
          9. Set the startup project to be FirstDemo.Droid and press F5 to run the application
            Update 16/4/2018: For some reason the iOS App (Xamarin) project template still uses a package.config. During the update to the stable v6.0.0 package the package.config file in FirstDemo.iOS was removed, the reference in FirstDemo.iOS.csproj to MvvmCross was manually removed and the following ItemGroup added:
            <ItemGroup>
               <PackageReference Include="MvvmCross" Version="6.0.0" />
            </ItemGroup>

          The final code is available at https://github.com/nickrandolph/MvxPlus1DaysOfMvvmCross/tree/master/Mvx-00-FirstDemo

          To get this to work I would suggest running the latest Visual Studio for Mac or PC. Hit me up on Twitter or Slack if you have any issues following the steps or running the samples.

          Progressive Web Apps–Are these a “thing” yet?

          Maximiliano Firtman has a great post that discusses the current state of play of Progressive Web Apps (aka PWAs). For me the stand outs are:

          - iOS hides the “Add to Homescreen” option within the Share extension

          - On iOS the ability to Add to homescreen isn’t available when using Edge or Chrome, despite the Share extension being a common across applications.

          - Lack of push notifications is a major annoyance from a user perspective – After installing iOS 11.3 I went and added the PWA version of Twitter (just go to https://mobile.twitter.com and add to homescreen). The app works great but the lack of any form of notifications is just crippling and means I now miss messages until I get prompted to go into the Twitter app. This alone is a reason for me to install the store version of the app.

          - PWAs still only get a limited cache, with no option to extend it with user consent, which is hardly enough to cache the static resources for a good responsive website, let alone provide offline data access

          - Windows support is still via an app coming from the store

          The upshot of this is that whilst Google is doing a great job in advocating for PWAs, the reality is that they’re still not ready for the prime time.

          Every day there are new technologies emerging; there are new frameworks available; there are new scenarios and devices to build for, so it becomes difficult as product owners, as developers, as technologists, to work out where to focus our attention. As we discussed in a recent article on App – Fomo before you jump into looking at technology it’s important to decide whether an app is even something you want to build. The true value of PWAs is that they are starting to bridge the cap between what the web can do today and the benefits offered by applications delivered by a store (eg place on the home screen, offline, push notifications). This in turn will ease make it easier to determine whether you truly need an app, or whether a modern responsive website (aka a PWA) will suffice.

          Slack, Teams and the Failings of the Universal Windows Platform (UWP)

          This is going to start of as a bit of a rant…. because it is – I’ve been building desktop and mobile applications using .NET since the first version of the .NET framework shipped many moons ago. In that time we’ve seen the rise and fall of various frameworks, patterns and technologies, all of which were supposed to make our lives as developers, designers and hopefully users better. Whilst the web seems to be this slowly devolving of JavaScript rot, you’d have thought that the .NET Framework after so many years would be everything that a developer needs in order to build amazing apps. Unfortunately, no, some idiot decided it would be great to run all that web-junk inside a native application.

          This brings me to the heart of my rant: Depending on our customers and suppliers, we toggle between Microsoft Teams, Slack, Skype, Skype for Business (now mostly deprecated in favour of Teams), HipChat, Hangouts and even Messenger. Whilst we all love to complain about how bad Skype is, the reality is that newer tools such as Teams and Slack are even worse. Both Slack and Teams are built using Electron and as far as desktop applications go, they are both as nasty as each other. They’re both slow; the user interface on both is painful and in no way takes advantage of the fact that I’m running on Windows. The operative word being Windows <<<—it has an S. I have to switch between multiple Slack channels and multiple Teams on a daily basis – they’re all in the same window; switching between them is slow (10-20secs); and it’s hard to keep track of conversations because notifications either don’t work, or are buried behind a single dot (not even a count as to how many unread messages).

          So why is it that things are so bad….. well it’s because the other options are no better. Take for instance the Universal Windows Platform – which is now only really Universal to desktop and Xbox because realistically they’re the only targets that you’ll consider (save some end cases for IoT and Hub). What a missed opportunity for Microsoft – they could have nuked the failed Xamarin Forms experiment in favour of extending UWP to really be the Universal Application Platform (UAP – oh wait, that’s the internal target framework for UWP already!!!); instead they’re sinking continued development effort into Xamarin Forms in the hope that it’ll one day be a viable alternative to Electron, Flutter, React Native….

          Talking of Xamarin Forms, is this such a bad platform? Well no, I actually quite like Xamarin Forms and I’ve personally invested a lot of time recently trying to help MvvmCross get to a stable v6 so that it can better support Xamarin Forms development. However, I would say that if you’re building for Xamarin Forms and you’re not using a third party Mvvm framework, you really need to – Microsoft’s continual assertion that Xamarin Forms has everything you need is just plain misleading and just leads to poorly architected applications.

          So, what is bad about Xamarin Forms? Well it’s hamstrung between at least three platforms (iOS, Android, Windows… Tizen, WPF….) in that they made a decision to rely on the native controls for each platform. React Native has a similar issue, since they decided on a similar approach. Flutter on the other hand has platform independent rendering and for that it’s getting a lot of attention. The design guidance from years ago that you should build for the platform UI is just plain wrong – you’ll end up with an application that just looks bad (lipstick on a pig!). You need to build applications that work for your brand – don’t design it multiple times, build it to suit your brand and your needs. You may decide to adopt some platform UX but the reality is that you want a button in your app to look the same on all platforms.

          Anyhow, enough of a rant about the failings of desktop apps…. until next time, enjoy losing hours of your day to responding to messages on Teams, Slack etc

          PWA Follow Up

          It’s clear that talking about Progressive Web Applications (PWAs) is all the rage. I noticed today that fellow Microsoft MVP, Adam Pedley who runs the Xamarin Help website and blog, posted about where PWAs and Xamarin.Forms fit. Whilst I’m not sure I agree with his opening statement about PWAs being started by Google (there is a long legacy of different browsers providing pseudo-offline features which pre-date the term PWA, so the concept itself isn’t new), I will definitely agree that it has been Google that has been championing the cause, with Microsoft adding some behind the curtain support (eg PWABuilder.com). One of the most interesting points that’s worth highlighting is the disconnect between the device features/capabilities that the web and client applications (native, Xamarin or Xamarin Forms) can take advantage of. Whilst the difference is being progressively eroded, there are still plenty of areas where a client application is the way to go. Shout out to https://whatwebcando.today/

          image