Nick's .NET Travels

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

Getting Started with Xamarin.Forms and Multi-Targeting in Visual Studio

I’ve walked through this a couple of times in the past (last year and in the Mvx+1 series I started) but I wanted to do an updated post to firstly point out that the getting started process in Visual Studio has stabilized quite a lot and the process of getting a new Xamarin.Forms project up and running is quite smooth. The second thing I wanted to add is how, and why, you can setup your .NET Standard libraries to be multi-targeted – this also has come a long way.

Note: I’m running Visual Studio 15.8 preview 5, so your experience may vary a little if you’re running a different version of Visual Studio. Before I get started I try to make sure all my components are up to date, including my MacMini which is what I use for building/debugging iOS applications.

Let’s get started by creating a new solution within Visual Studio, using the Mobile App (Xamarin.Forms) project template

image

This will prompt you to select what template to use, in this case we’re going to create a project based on a Blank template. In actual fact this template isn’t blank; it has 1 page which is required in order for the application to build and run. Also, make sure you select the .NET Standard Code Sharing Strategy. DO NOT select Shard Project – this options in my opinion should now be deprecated as multi-targeting is a much better option for achieving this same outcome.

image

After clicking OK to create the project, you’ll want to make sure you can successfully build all projects.

Next open the NuGet package manager for the solution and update all packages to the latest stable. In my case I just had to update Microsoft.NETCore.UniversalWindowsPlatform and Xamarin.Forms.

Now, make sure that each platform (i.e. iOS, Android and UWP) compiles and runs. Technically you don’t need to do this but if you run into difficulty later, at least doing a run check here gives you a “last known good” state to revert to. On that note, after checking that each platform runs, I would be making the initial commit to source control for your solution.

Next we’re going to add a new project based on the Class Library (.NET Standard) project template. This will be our Core project that will contain all our view models, services and business logic for the application.

image

The new project will come with Class1. Rename both the file and class name to MainViewModel.

Next we’re going to do a bit of a tidy up. By default the project that contains the XAML for the application (i.e. App.xaml) and for the main page of the application (MainPage.xaml) was given the same name as the solution itself. I’m not a big fan of that so I rename this to have the UI suffix. To do this you need to remove the existing project, rename the folder and project name, and add the existing project back into the solution. Don’t forget that you’ll need to update the namespace for both App and MainPage classes (in both XAML and code behind files) to include UI (e.g. the full type name of the MainPage class should be StrataPark.UI.MainPage)

After renaming the UI project, we need to double check that all the projects have the correct references. The only project reference the UI project should have is to the Core project

image

All three of the head projects (i.e. for iOS, Android and UWP) should reference both the Core and UI projects

image

Now’s another time to check that everything builds and runs (all three platforms) and then commit your changes!

Both the Core and UI projects are currently just .NET Standard 2.0 projects. This means that all code is the same for all platforms. By making these projects multi-targeted, we can enable platform specific code to be included where necessary. This is similar to the way shared libraries used to work. However, the difference is that the code stays in a separate assembly, away from the head projects.

To make use of multi-targeting, first create a file called global.json in solution folder, with the following contents:

{
     "msbuild-sdks": {
         "MSBuild.Sdk.Extras": "1.6.47"
     }
}

The MSBuild.Sdk.Extras package extends the raw multi-targeting support provided by Visual Studio/MSBuild. For both Core and UI projects, edit the csproj and replace the default TargetFramework element at the beginning of the file with the following (make sure you include the Project element as this sets the Sdk to use)

<Project Sdk="MSBuild.Sdk.Extras">
   <PropertyGroup>
     <TargetFrameworks>netstandard2.0;Xamarin.iOS10;MonoAndroid81;uap10.0.16299</TargetFrameworks>
   </PropertyGroup>

  <ItemGroup>
     <Compile Remove="Platforms\**\*.cs" />
     <None Include="Platforms\**\*.cs" />
   </ItemGroup>
  
   <ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) ">
     <Compile Include="Platforms\Netstandard\**\*.cs" />
   </ItemGroup>
  
   <ItemGroup Condition=" $(TargetFramework.StartsWith('uap')) ">
     <Compile Include="Platforms\Uap\**\*.cs" />
   </ItemGroup>

  <ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.iOS')) ">
     <Compile Include="Platforms\Ios\**\*.cs" />
   </ItemGroup>

  <ItemGroup Condition=" $(TargetFramework.StartsWith('MonoAndroid')) ">
     <Compile Include="Platforms\Android\**\*.cs" />
   </ItemGroup>

If you take a look at the code that was added to the csproj, you can see that there are some conditional inclusions based on the target platform. We’ll make use of this to return a platform specific welcome text for our application.

Add a Platforms folder to the Core project

Add Netstandard, Ios, Android and Uap sub-folders to the Platforms folder

Add a file called MainViewModel.Platform.cs to each sub-folder of the Platforms folder with the following text. Replace Netstandard with the name of the platform (i.e. the sub-folder name)

public partial class MainViewModel
{
     private string PlatformWelcomeText => "Welcome from Netstandard";
}

Next, we’ll modify the MainViewModel.cs file. Note how the WelcomeText property returns the platform specific text

public partial class MainViewModel
{
    public string WelcomeText => PlatformWelcomeText;
}

In the MainPage.xaml, add a new Label element that is bound to the WelcomeText property

<Label Text="{Binding WelcomeText}" />

In the codebehind for the MainPage.xaml, add the following code to the end of the MainPage constructor

BindingContext = new MainViewModel();

Now when we build and run the application on each platform, we’ll see a platform specific welcome.

image

This technique can be used to include all sorts of platform specific code within your application, making it easier to deal with the Mvvm abstraction when you need to tie into platform specific APIs. In the past you’d have typically had to create a service in the head project, or some other clumsy workaround.

Functionality and Usability beats Visual Design and Animations any day of the week!

Since Windows 10 was released I’ve periodically opened and attempted to use the Mail and Calendar applications that come preinstalled and in theory provide an integrated experience. As far as UWP applications go, there aren’t many that I look to as great showcases of what the platform is capable of but I figured that Microsoft would invest in their first party applications (there’s also Maps and a few others). It’s taken a few iterations but both Mail and Calendar are actually working quite well – they both support multi-window (although it’s a tad annoying that you can’t tell it to open items in a new window by default), and the UI generally has a lot of polish. However, that’s pretty much where the fairy tale ends.

The reality is that the Mail and Calendar applications are separate applications, and thus when you attempt to do things like “create a meeting from an email”, something that’s a simple drag and drop in Outlook, you are completely out of luck. Further more, despite quite a lot of effort having gone into the visual design, I still find that I’m struggling with basic things like scanning my email and seeing which items are read/unread and which ones I should be focussing on.

I know that these applications aren’t designed as a complete substitute for Outlook but I do wonder who makes the decisions on where the investment in these products is spent. Is there no focus on productivity, or is it just a competition to have the best looking design?

Speed up development with Multi-Targeted Visual Studio Projects

One of the biggest changes that MvvmCross undertook at the beginning of the year was to switch over to using Multi-targeting in Visual Studio. Instead of having a lot of platform specific projects, multi-targeting made it possible to create a single MvvmCross project that had multiple target frameworks. MvvmCross leverages Oren’s MSBuild.Sdk.Extras nuget package which allows us to define the list of target frameworks using the TargetFrameworks element in the csproj file (note that this is different from the default singular TargetFramework element which usually exists).

<TargetFrameworks>netstandard2.0;net461;Xamarin.iOS10;Xamarin.Mac20;Xamarin.TVOS10;Xamarin.WatchOS10;MonoAndroid81;tizen40;netcoreapp2.0;uap10.0.16299</TargetFrameworks>

Now, instead of ~220 projects, the MvvmCross.sln now has 57 projects. However, this transition comes at a cost. Firstly, defining all the target frameworks like this will mean that it won’t compile on Mac because UWP doesn’t exist there. MvvmCross addressed this by including some conditional logic to detect whether the solution was being built on Windows or not.

<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' "> netstandard2.0;net461;Xamarin.iOS10;Xamarin.Mac20;Xamarin.TVOS10;Xamarin.WatchOS10;MonoAndroid81;tizen40;netcoreapp2.0;uap10.0.16299</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' "> netstandard2.0;net461;Xamarin.iOS10;Xamarin.Mac20;Xamarin.TVOS10;Xamarin.WatchOS10;MonoAndroid81;tizen40;netcoreapp2.0</TargetFrameworks>

The second problem is that building the solution became incredibly slow. Every change to the core MvvmCross project meant it had to be recompiled for each target framework. Luckily this doesn’t impact developers using MvvmCross, but it does mean that making changes to MvvmCross is a painful process. This is made worse by the weak support within Visual Studio for multi-targeting, often resulting in having to clean bin/obj folders, restarting VS etc.

Most of the time when working on a feature or a bug in MvvmCross we’ll be targeting one platform; at least until we have it working, and then we’ll test on the other platforms. It would be really nice if Visual Studio supported this workflow, allowing us to effectively disable compilation of the platforms we’re not interested in.

Recently we made a change to the MvvmCross projects to add further conditional logic:

<PropertyGroup Condition=" '$(TargetsToBuild)' == 'All' ">
   <TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">netstandard2.0;net461;Xamarin.iOS10;Xamarin.Mac20;Xamarin.TVOS10;Xamarin.WatchOS10;MonoAndroid81;tizen40;netcoreapp2.0;uap10.0.16299</TargetFrameworks>
   <TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard2.0;net461;Xamarin.iOS10;Xamarin.Mac20;Xamarin.TVOS10;Xamarin.WatchOS10;MonoAndroid81;tizen40;netcoreapp2.0</TargetFrameworks>
</PropertyGroup>

<PropertyGroup Condition=" '$(TargetsToBuild)' != 'All' ">
   <TargetFrameworks Condition=" '$(TargetsToBuild)' == 'Android' ">netstandard2.0;MonoAndroid81;</TargetFrameworks>
   <TargetFrameworks Condition=" '$(TargetsToBuild)' == 'Uap' ">netstandard2.0;uap10.0.16299</TargetFrameworks>
   <TargetFrameworks Condition=" '$(TargetsToBuild)' == 'iOS' ">netstandard2.0;Xamarin.iOS10</TargetFrameworks>
</PropertyGroup>

As you can see, this inspects the variable TargetsToBuild in order to determine what target platforms to build. This variable is defined in the Directory.build.props so that it can be referenced from any of the MvvmCross projects.

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
   <!-- <TargetsToBuild>All</TargetsToBuild>  -->
   <!--<TargetsToBuild>Android</TargetsToBuild>-->
   <TargetsToBuild>Uap</TargetsToBuild>
   <!--<TargetsToBuild>iOS</TargetsToBuild>-->
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' != 'Debug' ">
   <TargetsToBuild>All</TargetsToBuild>
</PropertyGroup>

To make sure that this option doesn’t affect Release builds (ie creation of nuget packages) if the Configuration isn’t set to Debug, TargetsToBuild is set to All. In the above code, the TargetsToBuild variable is set to Uap. This means that only the Uap (and netstandard) targets will be built – this is a massive performance gain when debugging.

Note: If you change the TargetsToBuild property you will most likely have to restart Visual Studio and/or force a rebuild of the entire solution but the performance gain you get out of using the TargetsToBuild variable is well worth it.

Debugging and Contributing to MvvmCross

As one of the maintainers of MvvmCross I quite often help triage issues that are raised on GitHub. Issues are a mixed blessing – it’s really important to us that the community logs any issues that they come across so that we have a mechanism to track and resolve them with each release. However, the flipside is that issues become a dumping ground for developers who use MvvmCross, have come across an issue that they want, or need, fixed – they log an issue and assume that other contributors, or the maintainers, will resolve the issue in a timely manner. Before I get into the body of this post which will drill into how to debug MvvmCross, as well as how to proactively contribute to MvvmCross, I want to reiterate the point that open source software, which includes MvvmCross, ships as-is. This means whatever expectations you have of it working, or working a specific way, or any expectations you have on how issues will get resolved, or how quickly they’ll get resolved, are wrong. The only things you really know for certain is that there is source code that’s available for anyone to access and contribute to, and there are some versions of the library that are available via NuGet so that they can be easily consumed by developers. Of course, with this said, the MvvmCross team, like other OSS, do strive to address issues as quickly as they can but we all have day jobs and lives that mean our contribution to OSS is limited. In this post I will be covering what you can do when submitting an issue to make it easy for someone to resolve your issue as quickly as possible.

Debugging with MvvmCross using Source Linking

Note: Source Linking doesn’t work with all platform. If you building a Xamarin.Forms application, it’s worth creating a UWP head just in case you need to debug an MvvmCross issue.

We often get issues raised, either via GitHub, Slack or Stack overflow, that start along the lines of “my application doesn’t start (or crashes) when I do …..” Because the issue often resides within a commercial product that the developer is working on, we don’t typically ask developers to share their solution. Instead what we typically ask is that they use the Playground sample that’s included with the MvvmCross source code and see if they can reproduce the issue.

However, before getting to this point, there is a step that can often help identify the cause of any issue, which is to setup and use source linking to step through the MvvmCross source code. Source Linking is a technique that’s been around for quite some time and is something that MvvmCross has setup to allow developers to easily step from their code, directly into the source code of MvvmCross without any complex setup process.

Getting source linking to work isn’t always as easy as it should be. There are a few websites that cover how to enable source linking (such as this post by Cameron Taggart) and they all basically say the same thing, which is that to enable source linking you need to check the Options >> Debugging >> Enable Source Link support checkbox in Visual Studio.

Update: Whilst you’ve in Options, you can uncheck the “Enable Just My Code” as this setting will mask any internal exceptions that may be thrown during start-up. In the current version (6.1.2) there is an issue whereby exceptions raised during the start-up sequence in the Setup class are swallowed, preventing start-up completing. This will manifest differently on each platform but for a Xamarin.Forms application it may result in a white-screen being displayed on start-up and never proceeding to the first page of the application. Unchecking this option will mean that VS will break each time an exception is raised, allowing you to see the cause of the exception.

image

However, what’s not covered is what do you do if this doesn’t work. I don’t have a definitive answer either but I did find that after I toggled a few of the options (eg Enable source server support) I was able to get source linking to work.

Once you’ve got Source Linking enabled, how do you use it? There are a couple of options but they amount to the same thing – you need to trigger some debugging action that will allow you to step through the source code. The first option, and one that will work if something is going wrong within MvvmCross that may be triggering an exception that’s handled/swallowed. In this case you’ll need to change your Exception Settings so that all Common Language Runtime Exceptions cause Visual Studio to Break. After changing this setting, if an exception is raised within MvvmCross, you’ll be able to step through the code at the point the Exception is raised.

 image

The next option is to put a breakpoint in a method that overrides a method defined within MvvmCross. For example in the ProxyMvxApplication class, which inherits form MvxApplication, we can override the ReigsterSetup method and place a breakpoint in the method.

image

When the breakpoint is hit, you can see in the call stack that there are methods in the MvvmCross library.

image

Double-clicking on one of these lines will trigger the source code to be downloaded so that you can then step through the code. However, before the source code is downloaded, you may see the following prompt:

image

At this point you can opt in or out of source linking for this debugging session. Once you agree to Download Source and Continue Debugging, the cursor will be taken to the appropriate line of code and you can continue your debugging session.

image

As you can imagine, being able to step through the MvvmCross code means that you can try to identify what might be causing the issue you’re seeing. It’ll also mean that should you need to log a GitHub issue, you can provide us with a much more detailed description of what’s going on.

Contributing to MvvmCross

Contributing to OSS can happen at various levels, mainly depending on the amount of time someone has available and their inclination to help the community. For most developers their first contribution to MvvmCross will be in the form of a new issue. When submitting an issue, it’s important that you select the most appropriate issue template as a starting point.

image

As a community we welcome all feedback and encourage developers to raise an appropriate issue. Whilst we will respond to “Questions and Help” issues, we’d prefer it if you reached out via Slack or StackOverflow and actually talk to us!

It’s important to remember that in order to follow up on an issue we need as much information as possible. For example, information on how to reproduce an issue is invaluable. Providing a series of steps on how to reproduce an issue is a good starting point, and will help reduce the amount of time it takes to try to work out what’s going on. Alternatively, instead of just listing steps, a better way to demonstrate an issue is to use the Playground sample that’s included within the MvvmCross source code and reproduce the issue there. Once you’re able to reproduce the issue, you can submit a PR for review which may form the basis for resolving the issue.

Quick Steps for Resolving Issues:

  • In your solution: enable all exceptions in the Exception Settings window of Visual Studio – this will point out if an internal exception is occurring
  • In your solution: enable source linking where possible – this will allow you to step through MvvmCross source to try to work out what’s going wrong
  • In the Playground sample app in MvvmCross: attempt to reproduce the issue
  • Ask on Slack (or Stackoverflow) for assistance from the MvvmCross community
  • Raise an issue on the MvvmCross GitHub
  • Submit a PR with the changes to the Playground sample that demonstrates the issue

Note: When submitting a PR, please mark the PR as work in progress by putting [WIP] at the beginning of the title. This will prevent the PR from accidentally being merged. Also, please link the PR to the issue so that it’s easy to understand the purpose of the PR.

You might be asking why I’m asking that you submit a PR. It’s for two reasons:

1) I’m lazy – when I read your issue, it requires quite a bit of effort for me to reproduce the issue. If you provide a PR, I can simply pull your branch, run up the Playground and see the issue for my self. Not only that, I can also commit changes directly on your branch which means I can fix the issue straight away.

2) I want you to join the MvvmCross community – you only really join the community when you start contributing code to the project. By getting you to submit a PR, you’re breaking the ice and getting involved. The PR is a WIP so there’s no judgment from the community; in fact they’ll be impressed that you’re willing to get involved. We’ll often reach out directly to you and discuss the issue.

The upshot is that by submitting a PR you have a much higher chance of getting your issue looked at #NoGuarantees

Good-bye HipChat, and don’t let the door hit you on the way out!

It was interesting to see this week that Atlassian doomed the future of HipChat and its successor, Stride, with an aggressive wrap up schedule, with the services set to be discontinued on February 15, 2019. At Built to Roam, as a consulting company, we use a number of messaging tools including Messenger, Skype, Skype for Business / Microsoft Teams, Slack, HipChat and a few others. The upshot is that none of these tools do a great job of even their primary function (i.e. chat conversation between two or more parties), as I’ve posted about previously.

As a couple of posts have indicated, the messaging market has become over populated – for a while it felt like I was installing a new messaging app every second day. When Teams first came to the market, there was a lot of criticism aimed at it because it was a primitive offering in comparison to both Slack and HipChat but it’s rapid growth has started to put pressure on other players in the market. I think a rationalisation of the market was due, and I’m not sorry to see the back of HipChat. As one of the older products in the market, it never quite understood the need for users to belong to multiple organisations and to be able to switch between them.

There are some posts that are talking up the closure of HipChat/Stride as an attempt by Slack and Atlassian to team up in the fight against Microsoft Teams. So the question is, will this make a difference? Will it slow the growth of Microsoft Teams? Will it help Slack win over the corporate space?

Recently, Microsoft Teams announced a free tier, which was one of the things that held a lot of smaller companies and teams from using Microsoft Teams. This move in itself has weakened Slack’s position in the market. However, the true hook for Microsoft Teams and in my opinion the sole reason for its wide adoption (because let’s be honest, it’s far from being a great product!), is that it allows users to sign in using their Office 365 / Microsoft 365 account. In other words, if your company has made, or is moving, to Office 365, you can use your existing credentials to sign into Microsoft Teams. And of course, once you do, you can see and communicate with all the other users in your organisation. Can do you do this with Slack? The short answer is no. The long answer is yes but you need to do a bunch of stuff, including pay a ton of money for stuff that should be out of the box (seriously like what the? https://get.slack.help/hc/en-us/categories/200122103-Workspace-Administration#configure-access-security).

The ridiculous thing is that integration into Azure Active Directory (i.e. use Office 365 and Microsoft 365 credentials) is pretty straight forward. Is there something that Slack can do to get the jump on Microsoft Teams? Yes, provide out of the box support to sign in using either G-Suite or Office 365 credentials. In the future there will be two types of organisation, those that use Office 365, and those that don’t. Most of those in the latter group will probably use some form of G-Suite, so providing out of the box support for G-Suite should be on the radar of any enterprise software.

I know this post has gone on a bit but my last point is that I wish services would stop charging a premium for improving the security of their service. Integration with Azure Active Directory and G-Suite should be include in the cheapest tier of any offering. Why would you compromise the security of your service and the data of your users by not providing this.

Who broke my messaging app?

Prior to the iPhone the majority of applications written were for desktop based devices, whether they be for a Mac or PC, or in some cases both. With the iPhone we saw an entire industry of mobile app development opening up from being a very niche, specialist field, into a field full of imposters who claimed they knew how to build a mobile application, just because they were now able to build and publish an iPhone app. The first generation of iPhone applications weren’t anything special and in fact if you compared the sophistication of most iPhone applications from that era to those being written for other mobile platforms, they were definitely a case of “beauty over brains” – You have to hand it to Apple, as they really did make it easy to build high quality apps that looked great, even if they suffered from a lack of substance.

So hang on, how does this relate to my messaging app? Well, whilst the quality and complexity of mobile applications has increased, one thing that hasn’t is that they are all single window. Due to the screen real estate, mobile application have a single window. With the introduction iPad and other tablets, we saw the use of split screen and master-detail style layouts but even these were all contained within a single window. In the context of a messaging application, whether it be Skype, Messenger, WhatsApp, Twitter etc, the layout is all basically the same – you have a list of contacts and/or groups, you tap into a contact or group and are taken to a chat interface where you can message. In the case of devices with more screen, often the contacts/groups will be listed in a pane on the left or right of the current conversation but in both cases, if you have multiple conversations going, you have to switch between active conversations.

I have nothing against the single window view when working on a mobile device, and I think I’m ok with it on a tablet device but when we graduate to a laptop/desktop we enter a world of inefficiencies and poor user experience. My mobile comes with me virtually everywhere I go but when I’m working, or at home surfing the internet, I’m typically on my laptop (as an aside, I’m running the Surface Book 2 i7 15” and it’s an amazing bit of kit – highly recommend it!). I’ll often have a combination of Messenger, Skype, Teams, LinkedIn and Twitter open and will switch between conversations within each as required. However, typically at any given point in time I’ll be involved in one or two conversations, and it’s really annoying to have to keep switching between these conversations and whatever else I might be doing. For example I might be having a couple of DM conversations on Twitter but at the same time catching up with what’s been happening on my main feed – this means I have to keep switching between conversations, rather than being able to keep them both open at once.

Now I think you can see where I’m going with this – I run an operating system that I think most of you will have heard of…. Windows…. not “Window” but “Windows” <<- plural!!

Why is it that very few modern applications make use of multiple-windows? Well, it’s because of the iPhone – for the last decade app developers (and don’t forget all those app designers who can’t comprehend how an app can use multiple windows) have been building apps that only use one window because building iPhone applications was where the money was, and still is. It doesn’t help that Android apps are also predominately single window.

Let’s go back a few years an look at some user interfaces that have been discarded in favour of the now pathetic single-window messaging app experience:

Do you remember mIRC?

Whilst it was technically one window, it did support having multiple conversations open at the same time using child windows.

Related image


Do you remember MSN/Live Messenger?

It had multiple windows that you could open an arrange how you like. In fact you could force a window to stay on top of everything so it didn’t get obscured by other windows you might be switching between.

Image result for live messenger multi window


So where to from here?

Well the good news is that Windows app developers already have great multi-windowing support out of the box – you just need to build your application to take advantage of it (see https://docs.microsoft.com/en-us/windows/uwp/design/layout/show-multiple-views).

The bad news is that I doubt any of the major messaging services will take advantage of this in the short term, so we’re going to be stuck with a sub-optimal experience. Neither Skype and Teams, both Microsoft products, have any form of multi window support. Messenger still looks like it has been thrown together by some intern at Facebook, so I doubt we’ll see any innovation there. Twitter is a PWA, so I’m not sure how easy it will be for it to take advantage of multiple windows – having said that, as a PWA it can access any of the Windows 10 APIs, so there should be no reason why it can’t spawn additional windows.

Microsoft Whiteboard

I noticed the other day that Microsoft have added another app to the suite of apps that are available to Office 365 subscribers, Microsoft Whiteboard (https://products.office.com/en-us/microsoft-whiteboard/digital-whiteboard-app). On downloading it from the Store I was immediately impressed with the overall look and feel of the app – very professional and clearly showcases what can be done with the Windows platform.

Having said this, here are my immediate frustrations:

Where are the apps for other platforms?

Namely iOS, Android, Web, MacOS – it’s very transparent that this is a push to promote how great the inking experience is on Windows but for this to be a viable solution for businesses it needs to be available anywhere

Why upload PNGs?

Being a developer I immediately ran the app through Fiddler and what shocked me was that PNGs are being uploaded. I haven’t delved into how the synchronisation process works when multiple people are collaborating but I can’t imagine any scenario where uploading PNG is efficient. If you look at what other shared drawing experiences do (eg http://cosketch.com) there is no sharing of image, rather the line segments are sent back and forth.

Why isn’t this a Control

Again with my developer hat on, this shared whiteboard needs to be made available as an Office 365 control that developers can simply drop into their application in order to integrate a shared whiteboard experience. As more applications are built that tap into the Microsoft Graph and leverage the fact that users are connected with either an MSA or an Office 365 account, having rich component such as this would significantly cut development time and make it easier to build amazing applications.

Overall I’m impressed with Microsoft Whiteboard and hope that this is a sign of some of the great innovation that the Microsoft 365 platform will bring with it.

Building a TipCalc using Platform Uno

Recently I’ve been playing around with Platform.Uno – I’ve long held the view that Microsoft’s Xamarin.Forms was a stop-gap in delivering a true cross-platform solution. Whilst Xamarin.Forms is a highly productive platform, it has some severe limitations, specifically around overriding the look and feel of the native controls. This is where Flutter has stolen a lot of mindshare, mainly because customers and companies looking to build apps, no longer look for apps that match the platform style. They’re much more focussed on strong brand presence and great user experience, meaning that a great Material app on iOS will get better reviews and usage than a mediocre app that uses the default iOS style. Platform Uno attempts to deliver on what I believe the Universal Windows Platform (UWP) should have been – taking UWP XAML across iOS, Android and Web Assembly.

Anyhow, here goes with building a TipCalc. I’ll start with the basic UWP application:

I’ll create a separate project for our ViewModel:

Running the UWP app at this point gives an operational tip calculator

image

So now, let’s add some Uno goodness. We’ll start by moving the MainPage.xaml into its own class library:

  • Add a new project based on the Class Library (.NET Standard) project template, TipCalc.UI
  • Remove class1.cs
  • Add reference to project TipCalc.Core
  • Move MainPage.xaml and MainPage.xaml.cs to the TipCalc.UI project
  • Change namespace from TipCalc.UWP to TipCalc.UI for both MainPage.xaml and MainPage.xaml.cs
  • Edit TipCalc.UI.csproj to allow it to multi-target (ie generate multiple dlls that target UWP, Droid, iOS etc) and make sure correct build action is set for MainPage.xaml
  • Add reference to Uno.UI nuget package (currently in prerelease).
  • Final TipCalc.UI.csproj should look similar to

  • <Project Sdk="MSBuild.Sdk.Extras/1.5.4">
       <PropertyGroup>
         <TargetFrameworks>xamarinios10;MonoAndroid80;uap10.0</TargetFrameworks>
       </PropertyGroup>

      <PropertyGroup Condition=" '$(TargetFramework)' == 'uap10.0' ">
         <GenerateLibraryLayout>true</GenerateLibraryLayout>
       </PropertyGroup>

      <ItemGroup Condition=" '$(TargetFramework)' == 'uap10.0' ">
         <PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform" Version="6.1.5" />
       </ItemGroup>

      <ItemGroup>
         <PackageReference Include="Uno.UI" Version="1.31.0-dev.52" />
       </ItemGroup>

      <ItemGroup>
         <Page Include="MainPage.xaml">
           <SubType>Designer</SubType>
           <Generator>MSBuild:Compile</Generator>
         </Page>
       </ItemGroup>

      <ItemGroup>
         <ProjectReference Include="..\TipCalc.Core\TipCalc.Core.csproj" />
       </ItemGroup>
    </Project>

  • Add Uno.UI nuget reference to TipCalc.Core. Resulting csproj should look similar to

  • <Project Sdk="MSBuild.Sdk.Extras/1.5.4">
       <PropertyGroup>
         <TargetFrameworks>xamarinios10;MonoAndroid80;uap10.0</TargetFrameworks>
       </PropertyGroup>

      <ItemGroup>
         <PackageReference Include="Uno.UI" Version="1.31.0-dev.52" />
       </ItemGroup>
    </Project>

  • Add reference to TipCalc.UI to TipCalc.UWP

By all accounts at this point you’ve done a fair bit of lifting with out much to show for it. In fact, because of some absolute genius coding by Microsoft, if you run the UWP application at this point you’ll most likely see a System.AccessViolationException when attempting to navigate to MainPage

image

This seems to be an issue where you’re attempting to navigate to a page that’s defined in a separate assembly and there are no other XAML pages defined in the head (ie UWP) project. Simple solution is just to add a dummy page to the UWP project that you’ll never use…. but seriously Microsoft??? Oh, and this isn’t the first time this has been pointed out (see https://social.msdn.microsoft.com/Forums/windowsserver/en-US/4efa91ad-fa8f-45f0-9864-c2fd2b24477c/uwpc-accessviolationexception-when-navigating-froma-another-assembly?forum=wpdevelop which links to an old post http://danielvaughan.org/posts/uwp/2015/08/15/UWP-AccessViolationException-when-Navigating-to-a-Page-in-Another-Assembly/)

Right, so the question is – after all this effort, how are we any closer to having a cross platform application. Well, let’s spit out the Android build:

  • Add a new project based on the Android App (Xamarin) project template, TipCalc.Droid
    image
  • Use the Blank App template
  • Uninstall any of the Xamarin.Android.Support nuget packages that are installed by default
  • Add reference to Uno.UI nuget package
  • Add reference to both TipCalc.UI and TipCalc.Core
  • Add a reference to Mono.Android.Export
    image
  • Add App.xaml and App.xaml.cs from the TipCalc.UWP project to the TipCalc.Droid project As Link
    image
  • Alter MainActivity to the following

  • [Activity(
         MainLauncher = true,
         ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize,
         WindowSoftInputMode = SoftInput.AdjustNothing | SoftInput.StateHidden
    )]
    public class MainActivity : Windows.UI.Xaml.ApplicationActivity
    {
    }

  • Add an Application class as follows

  • [global::Android.App.ApplicationAttribute(
         Label = "@string/app_name",
         LargeHeap = true,
         HardwareAccelerated = true,
         Theme = "@style/AppTheme"
    )]
    public class Application : Windows.UI.Xaml.NativeApplication
    {
         public Application(IntPtr javaReference, JniHandleOwnership transfer)
             : base(new App(), javaReference, transfer)
         {
         }
    }

Now we’re good to go. Set the TipCalc.Droid to be the start up project and off we go. The app looks basically the same as it did on UWP

image

This took quite a bit of effort to get going but now that it’s there, you can imagine that productivity is going to be quite good. Next up I’ll add in the iOS project but I don’t envisage that, nor Web Assembly, being that hard from the samples I’ve seen to date.

Source code available at https://github.com/nickrandolph/UnoSamples

Developer + Python != Artificial Intelligence

As I mentioned in a previous post, artificial intelligence (AI) is one of the hottest topics going around the traps. Developers are always keen to jump onto the latest trends and topics, so naturally assume that they can bend their minds to the latest hype. Amazon, Google and Microsoft down play AI by offering pre-packaged solutions that can be bolted onto new or existing applications. I say down-play because they all but eliminate the need to focus too much attention on the analysis of data, building and validating an appropriate algorithm/model. For example you can build a custom vision service by throwing up a bunch of images, appropriately tagged, to train a model. Thus a developer with minimal AI skills can build and integrate such a service.

For developers who really want to build AI solutions, they can do a basic AI course (for example Microsoft’s Professional Program has an Artificial Intelligence track) but does this mean they’re an AI expert? What if they go and learn Python or R, does that make them an AI guru? The short answer is no – they’re still a software developer, not a data scientist.

If you’re a company that wants to add some AI to your application you should look beyond the basic claims by development companies that they “do AI” and verify what they mean. There are specialist data centric companies out there, like Analytics 8, that have a history in working with big data – if you have vast data repositories, this is where you should start. Once you’ve defined what your AI solution is, then you can engage with a developer to integrate the model into your application, website or bot.

Microsoft’s Missed Opportunity for Offline Data

As a rich client application developer one of the most complex piece of building any application is providing support for working offline. Historically most consumer applications haven’t had strong requirements for working offline (Facebook, Twitter, Instagram etc don’t make much sense when you’re offline) but in the enterprise there are a lot of scenarios where offline data is an important piece of any application.

Ever since the days of Windows Mobile (v1, ie what used to be Pocket PC) there have been libraries/frameworks produced by Microsoft to make it easy to build applications that synchronise data. A short list of these include:

- Merge Replication

- Sync Framework (multiple versions)

- Azure Mobile Services

Unfortunately nearly all of these struggled as they attempted to synchronise relational data and there was no clear guidance from Microsoft on how they should be used.

Recently the other cloud players have been taking Microsoft to task by releasing frameworks that make it easy for app developers to get started. Note the important piece here are that these, like Azure Mobile Services, form part of the PaaS offering for the cloud provider. The implication being – if a cloud provider can get you to sign on to one or more PaaS services, they have you for the life of the application. Unlike IaaS or containers, PaaS makes it very difficult (not impossible) to simply switch to another cloud provider.

Over at Amazon, they have AWS AppSync

Over at Google, they have Google App Engine

Exploring Artificial Intelligence (AI) Services from Cloud Vendors

Currently the market is buzzing with talk of artificial intelligence (AI) and/or machine learning (ML) along with the power of the cloud and edge computing. Talking to various people across different industries there’s genuine excitement about the change that is about to take place. However, what businesses struggle with is how to take the leap and get started. Most organisations, whilst they may have been capturing and managing data for quite some time, don’t have luxury of having a data scientist on staff. Luckily there are a range of services provided by different cloud providers that are in effect commoditizing artificial intelligence.

In a previous post I covered working with Microsoft’s custom vision service to do number plate recognition, which is one out of many services offered by Microsoft under the banner of their cognitive services. In fact, the custom vision service is one out of a number of vision related services:

- Computer Vision

- Video Indexer

- Custom Vision

- Face

- Content Moderator

But Microsoft isn’t alone in provision vision and image services. Google have a set of AI services, which include:

- Cloud Vision API

- Cloud Video Intelligence

And of course AWS have similar services, such as their Amazon Rekognition service.

Each of these services have their strengths and weaknesses but the question really starts with the problem that needs to be solved. Does it make sense for a business to investigate these services? Are there opportunities to make use of these services?

MVX=1F: TipCalc with Xamarin.Forms (MVX+1 days of MvvmCross)

In this post I’m going to extend the TipCalc to include Xamarin.Forms targets, similar to what we did in the post MVX=0F: A first MvvmCross Application (MVX+1 days of MvvmCross)

Adding Xamarin.Forms

Note: The following instructions can be applied to any project by simply replacing TipCalc with the name of your project

  1. Add a New Project based on the Mobile App (Xamarin.Forms) template 
    image

  2. In the New Cross Platform App dialog, select Blank App, check the Platforms you want, select .NET Standard and click OK
    image

  3. Upgrade the Xamarin.Forms NuGet to latest for all four Forms projects
  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)

Update the TipCalc.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

Update the FirstDemo.Forms.Uwp project

  1. Update Microsoft.NETCore.UniversalWindowsPlatform
  2. Add reference to TipCalc.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, TipCalc.Forms.App>, Core.App, TipCalc.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
  2. Upgrade Xamarin.Android.Support.* to latest for the Forms.Android project
  3. Add reference to TipCalc.Core
  4. Change MainActivity inheritance, remove code except for a constructor:
    public class MainActivity : MvxFormsAppCompatActivity<MvxFormsAndroidSetup<Core.App, App>, Core.App, App>
    {
    }

Update the TipCalc.Forms.iOS project

  1. Add reference to TipCalc.Core
  2. Changed inheritance of AppDelegate
    public partial class AppDelegate : MvxFormsApplicationDelegate<MvxFormsIosSetup<Core.App, TipCalc.Forms.App>, Core.App, TipCalc.Forms.App>


Adding TipCalc Xamarin.Forms Layout

Update the TipCalc.Forms project by updating the FirstView.xaml with the following XAML.

<?xml version="1.0" encoding="utf-8" ?>
<views:MvxContentPage
     xmlns:views="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
     xmlns="
http://xamarin.com/schemas/2014/forms"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              x:Class="TipCalc.Forms.Views.FirstView">
  
  <StackLayout>
         <Label Text="SubTotal"/>
         <Editor Text="{Binding SubTotal, Mode=TwoWay}"/>
         <Label Text="How generous?"/>
         <Slider Value="{Binding Generosity, Mode=TwoWay}"
                     Minimum="0"
                     Maximum="100"/>
         <Label Text="Tip:"/>
         <Label Text="{Binding Tip}"/>
         <Label Text="SubTotal:"/>
         <Label Text="{Binding Total}"/>
     </StackLayout>

</views:MvxContentPage>

That’s it – there’s nothing more to do in order to add Xamarin.Forms targets (iOS, Android and UWP) to the TipCalc

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.