Getting Started with System.CommandLine

Before I get distracted with a story, this post is going to be a quick intro into creating your first command line app, using the specifically named System.CommandLine library.

All the code for this post lives in https://github.com/mattleibow/CommandLineApp

Contents

If you are just here for code snippets, you can jump to it:

But before we get too crazy, let’s talk about the why of the concept…

Why?

I enjoy writing code… Just in case you don’t know by now. A bit too much, I might add. But, I also enjoy setting up unit tests and CI/CD to prove that my code works.

Azure DevOps and GitHub Actions are powerful and allow me to pretty much do whatever I want. I also combine this with Cake to get that sweet, sweet C# scripting ability. I could write everything in the pipeline YAML, but this has 2 downsides:

  1. No local execution for testing
  2. No sharing between pipelines or tooling (lock in)

One way to avoid all this is to use a big Cake script so that I can just have a single line of execution in my build.cake:

dotnet cake

This is pretty cool, but it now makes me write more C# code (which is awesome) when all I wanted to do was a generic action. I could create a Cake addin, but this forces me to use Cake – even when I don’t need to. So the downsides of this are:

  1. Slightly more complex task of creating a Cake addin
  2. No sharing with anything other than Cake scripts

So, what can we do to avoid all the downsides, but still have a “tool” that allows us to generically run a chunk of work, but have no pipeline or scripting restrictions?

Introducing the (not so new) .NET Core Global Tools! This is pretty much a way to write a small console app that can be quickly and easily installed from NuGet. All you need is an install of .NET Core – which is most likely already available to you… since you are reading about .NET and C# development.

For example, to install the Cake tools for running your build script, you just need:

dotnet tool install -g cake.tool

That is it! It will pull down and install the tool, and then you can call:

dotnet cake

All right, so now that we know we want to use .NET Core tools, how do we get started? But, before we do that, we need to have a look at what a .NET Core tool is and what System.CommandLine does.

What?

A .NET Core tool is pretty much an ordinary NuGet package, but has the ability to be installed as a command line tool – rather than just as a dependency in another project.

.NET Core Global Tool

You can read more on the docs website, but here is an example .csproj that can be packed into a tool:

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp3.1</TargetFramework>
        <PackAsTool>true</PackAsTool>
    </PropertyGroup>

</Project>

The special line (or rather property) is the PackAsTool property. This can also be set on the command line during a build, but since this is only going to be a tool, I add it to my project file.

That property only affects the build when running a pack, so everything else is still the same. When wanting to test out the app during development, you can still use the old:

dotnet run -- <args>

The -- indicates that you are going to pass whatever is to the right directly to the app itself.

The Command Line App

But now, let us move into the code… First, when creating a console app, we are greeted with some exciting code:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");
    }
}

Even though this is pretty exciting, it is not really useful. If we want to make an actual app, we have to manually parse the args parameter and then do work. We also have to let the caller know if things went well or not using the exit code. We might even want to do asynchronous code using async/await.

So, I like the more modern, more powerful version:

class Program
{
    static void async Task<int> Main(string[] args)
    {
        Console.WriteLine("Hello World!");

        return 0;
    }
}

Look at that sweet command line app that is capable of anything!

But it does nothing yet! We still have to take that unassuming string[] args and turn it into some real work.

We could do that ourselves… we could, but we are not crazy… at least not in that way. So, this is where we pull in the fancy new System.CommandLine package. You can read all the docs and wikis and samples in the command-line-api repository, but I am just going to jump in with some example setups.

The Basic-est

As with all things, I want to jump in at the deep end – I actually did this before this very post – and flail around for a few hours/days (is there a difference?) and then eventually have a working app. But now that I look smart, I’ll start at the beginning.

Command Line Apps

To get started, many apps don’t need asynchronous code and they only have a success or a crashed result. The crash automatically sets the exit code to 1 (bad), and a “no crash” to 0 (good). So, for this example, we are going to stick with the synchronous void return:

class Program
{
    static void Main(string[] args)
    {
    }
}

Now, in order to add the command line parsing, we can install the System.CommandLine package and then when that is done, start writing code. All apps start with a RootCommand and may or may not have sub commands. Most commands have a set of Option items and possibly an Argument item. And then, there is a Handler that actually does the work.

So, let’s have a look at a basic command:

tool --option-a --option-b value "argument value"

This has a few parts:

  • tool is the command/app name
  • --option-a is a flag option – it signifies a simple boolean value
  • --option-b value is a value option – it allows a value to be associated with it
  • "argument value" is the argument that is passed – it typically provides the information that is core to a command

If we are to translate this into a method signature, we might do this:

ExecuteTool(bool optionA, string? optionB, string argument);

And this is exactly what System.Commandline does for us!

Our Greeting App

So, let’s finally get to the part where we write out the bits to do this! Enough delays!

The first thing we do is create the objects and set a handler. We are going to use a RootCommand with one Argument item and two Option items. We are then setting the Handler using the helper method CommandHandler.Create<T>. Finally, we call Invoke to actually run the app.

static int Main(string[] args)
{
    var cmd = new RootCommand
    {
        new Argument<string>("name", "Your name."),
        new Option<string?>("--greeting", "The greeting to use."),
        new Option("--verbose", "Show the deets."),
    };

    cmd.Handler = CommandHandler.Create<string, string?, bool, IConsole>(HandleGreeting);

    return cmd.Invoke(args);
}
static void HandleGreeting(string name, string? greeting, bool verbose, IConsole console)
{
    // TODO: a great app
}

The IConsole parameter in the handler is a magical one. It allows us to write to the console without taking a strict dependency on the Console type. We don’t need it, but it does allow us to keep our hands clean.

If we look at the definition of the command, we can see that there are some items that map to the signature of the handler method. This is one of the very exciting things about System.CommandLine, it will map from the strings in the args to the strongly typed arguments in the handler.

It can do the primitives as well as enum values. It also has a way to control how many of the options are allowed and what values can be passed to them. There are even ways to hook up validation so that by the time the handler is called, everything is ready to go and the values are clean.

First Output

Let’s run the app! (I am using dotnet run -- so I don’t have to pack and install)

Required argument missing for command: CommandLineApp

Usage:
  CommandLineApp [options] <name>

Arguments:
  <name>    Your name.

Options:
  --greeting <greeting>    The greeting to use.
  --verbose                Show the deets.
  --version                Show version information
  -?, -h, --help           Show help and usage information

Just look at that nice error message and help output! We did nothing, and we are already getting things working! We get a nice --help and --version args as well! It’s amazing!

But hey! What is that? We only have the long form of the options!

Option Aliases

Imagine how tired we will get typing in “–greeting”. So many characters! We want to do “-g”! How do we do that? Well the first value in the Option constructor allows us to pass an array of aliases:

new Option<string?>(new[] { "--greeting", "-g" }, "The greeting to use."),
new Option(new[] { "--verbose", "-v" }, "Show the deets."),

OK, I got distracted already… If we run dotnet run -- --help then we get a nice output:

Usage:
  CommandLineApp [options] <name>

Arguments:
  <name>    Your name.

Options:
  -g, --greeting <greeting>    The greeting to use.
  -v, --verbose                Show the deets.
  --version                    Show version information
  -?, -h, --help               Show help and usage information

Much better! Now that I fixed that, we can continue with the implementation.

The Handler

Our HandleGreeting method is a normal C# method:

static void HandleGreeting(string name, string? greeting, bool verbose, IConsole console)
{
    if (verbose)
        console.Out.WriteLine($"About to say hi to '{name}'...");

    greeting ??= "Hi";
    console.Out.WriteLine($"{greeting} {name}!");

    if (verbose)
        console.Out.WriteLine($"All done!");
}

This is very simple, we have the 3 values we requested from the command line (with the optional greeting) and the magical IConsole from the library. We then go ahead and run as we would in any normal console app.

If I run this with dotnet run -- Matthew, and this is the output:

Hi Matthew!

We can also run this now with those fancy options. For example, to say “good morning” to a girl named “Indry” using the verbose output, we can run:

dotnet run -- -g "Selamat pagi" Indry --verbose

As you can see, we are mixing the short form and the long form of options as well as the placement of the arguments. The output of this is:

About to say hi to 'Indry'...
Selamat pagi Indry!
All done!

Pretty neat! We did no actual work. We just described the options we want, and then made a handler to match. System.CommandLine did all the rest.

The Sub-Command

Right… Now, what happens if we want to create a complex app with loads of features? For example, the .NET app itself? When you run dotnet, you have a good selection of “commands” or “sub apps” or “sub commands”. For example, there are commands like “restore”, “build” and “tool”.

Commands are a way of breaking up a single tool into multiple sub-tools to avoid the need for many tools. But it also allows for grouping of commands as a hierarchy.

For example, dotnet has several commands and sub commands:

dotnet
  restore
  build
  tool
    install
    uninstall

With these options, we can do things like this:

dotnet restore
dotnet build
dotnet tool install
dotnet tool uninstall

Instead of having many tools, we got one. In steam of having a complex set of arguments, we have commands and sub-commands.

And, we can do this as well by simply nesting our commands when we set it up. Before we go extreme, we are going to take our simple app, and make it into a sub-command. This is not too useful as is, but it demonstrates the bits needed:

static int Main(string[] args)
{
    var greeting = new Command("greeting", "Say hi.")
    {
        new Argument<string>("name", "Your name."),
        new Option<string?>(new[] { "--greeting", "-g" }, "The greeting to use."),
        new Option(new[] { "--verbose", "-v" }, "Show the deets."),
    };

    greeting.Handler = CommandHandler.Create<string, string?, bool, IConsole>(HandleGreeting);

    var cmd = new RootCommand
    {
        greeting
    };

    return cmd.Invoke(args);
}

That is it! No changes needed to the handler at all. The handler works exactly the same whether it is the root command or a sub-command. But this opens up the possibility to do much more. If we run the app now with dotnet run -- --help, we get a slightly different output:

Usage:
  CommandLineApp [options] [command]

Options:
  --version         Show version information
  -?, -h, --help    Show help and usage information

Commands:
  greeting <name>    Say hi.

We can also get the help for the greeting command using dotnet run -- greeting --help:

greeting:
  Say hi.

Usage:
  CommandLineApp greeting [options] <name>

Arguments:
  <name>    Your name.

Options:
  -g, --greeting <greeting>    The greeting to use.
  -v, --verbose                Show the deets.
  -?, -h, --help               Show help and usage information

The Command Tree

OK, so we have it done. We know how to create an app. We know how to add a sub-command. So, now we need to add moar!

Helper Extensions & Reflection Handlers

But, before we get too excited, I want to add a little tweak. If you look at the construction of the commands, you will notice the slightly different way in which I set the Handler property. This is correct, but it has a few drawbacks:

  1. It reaches a limit of 7 parameters in the generic arguments
  2. It is annoying to line up the generic arguments with the method signature
  3. It breaks the cool structure of the initializers

What to do? Extension Methods! Reflection!

Before you get all nervous, the reflection idea is the alternate way to connect the handlers with commands, so we are not going too crazy. And the extension method is really neat. And simple:

static Command WithHandler(this Command command, string name)
{
    var flags = BindingFlags.NonPublic | BindingFlags.Static;
    var method = typeof(Program).GetMethod(name, flags);

    var handler = CommandHandler.Create(method!);
    command.Handler = handler;
    return command;
}

Would you look at that? Nice and simple. It is basically using reflection to find the MethodInfo and pass that to CommandHandler.Create. It then assigns that handler to the command.

If we take our basic sub-command, we can simplify the code a bit:

static int Main(string[] args)
{
    var cmd = new RootCommand
    {
        new Command("greeting", "Say hi.")
        {
            new Argument<string>("name", "Your name."),
            new Option<string?>(new[] { "--greeting", "-g" }, "The greeting to use."),
            new Option(new[] { "--verbose", "-v" }, "Show the deets."),
        }.WithHandler(nameof(HandleGreeting))
    };

    return cmd.Invoke(args);
}

The handler is now inline and does not break the hierarchy layout. We could even make this an expression bodied member and have the Invoke called on the closing brace of the RootCommand, but I leave that up to you.

Anyways, lets get back!

The Multiple Sub-Commands

We can take all that we have done so far and join it all and keep adding new commands and sub-commands. And that is what I have done!

I am creating a 3 command app that supports some exciting invocations:

app greeting ...
app echo times ...
app echo forever ...

Check it out:

public static async Task<int> Main(string[] args)
{
    var cmd = new RootCommand
    {
        new Command("greeting", "Say hi.")
        {
            new Argument<string>("name", "Your name."),
            new Option<string?>(new[] { "--greeting", "-g" }, "The greeting to use."),
            new Option(new[] { "--verbose", "-v" }, "Show the deets."),
        }.WithHandler(nameof(HandleGreeting)),
        new Command("echo", "Stop copying me!")
        {
            new Command("times", "Repeat a number of times.")
            {
                new Argument<string>("words", "The thing you are saying."),
                new Option<int>(new[] { "--count", "-c" }, description: "The number of times to copy you.",
                    getDefaultValue: () => 1),
                new Option<int>(new[] { "--delay", "-d" }, description: "The delay between each echo.",
                    getDefaultValue: () => 100),
                new Option(new[] { "--verbose", "-v" }, "Show the deets."),
            }.WithHandler(nameof(HandleEchoTimesAsync)),
            new Command("forever", "Just keep repeating.")
            {
                new Argument<string>("words", "The thing you are saying."),
                new Option<int>(new[] { "--delay", "-d" }, description: "The delay between each echo.",
                    getDefaultValue: () => 100),
                new Option(new[] { "--verbose", "-v" }, "Show the deets."),
            }.WithHandler(nameof(HandleEchoForeverAsync)),
        },
    };

    return await cmd.InvokeAsync(args);
}

I am doing everything there! Asynchronous Task<int>, CancellationToken, void, default values and much much more!

My handlers are not to crazy either! It is amazing what this can do:

static async Task<int> HandleEchoTimesAsync(
    string words,
    int count,
    int delay,
    bool verbose,
    IConsole console,
    CancellationToken cancellationToken);

static async Task<int> HandleEchoForeverAsync(
    string words,
    int delay,
    bool verbose,
    IConsole console,
    CancellationToken cancellationToken);

private static void HandleGreeting(
    string name,
    string? greeting,
    bool verbose,
    IConsole console);

You don’t have to put everything into a single, massive class, but you can split it up into namespaces, multiple classes, nested classes or anything you like. System.CommandLine is the bit between string[] args and your methods.

If we run the app with dotnet run -- --help, we have a nice output:

Usage:
  CommandLineApp [options] [command]

Options:
  --version         Show version information
  -?, -h, --help    Show help and usage information

Commands:
  greeting <name>    Say hi.
  echo               Stop copying me!

We can also run help for a command! Try dotnet run -- echo --help:

More commands! Look:

echo:
  Stop copying me!

Usage:
  CommandLineApp echo [options] [command]

Options:
  -?, -h, --help    Show help and usage information

Commands:
  times <words>      Repeat a number of times.
  forever <words>    Just keep repeating.

I think my job here is done!

Start today. Make your command line apps cool. Be cool.

You can check out all this code on my GitHub: https://github.com/mattleibow/CommandLineApp

Templated Controls in Xamarin.Forms

Contents

Sometimes you want to create that awesome control, but also want the user to be able to totally customize it… What do you do? Create a templated control!

Xamarin.Forms has a pretty cool view that we can use: TemplatedView (API docs).

More information on how to use templated controls and page can be found in the docs: https://docs.microsoft.com/xamarin/xamarin-forms/app-fundamentals/templates/control-template

So, on this journey to create the best templated control, let us create a cool and exciting “confetti view” like this:

In most cases we would just create a single view, no need to template anything. But, we would also like to try out templated views… and the user may want to place borders, backgrounds or some other fancy thing. If we can support this, then why not?

The Control

So, how does this work? Very simple! All you need is a new type that is going to be the control. Make sure it derives form TemplatedView:

public class SKConfettiView : TemplatedView
{
}

There we go! All done! Thanks for reading.

Just kidding, we need to show how to use it!

This is just like a normal control, so we can add it to our page as we would any other control:

<ContentPage ...
    xmlns:controls="clr-namespace:SkiaSharp.Extended.Controls">

    <controls:SKConfettiView />

</ContentPage>

When we run the app, we will have an invisible control in the app. We can’t see anything, but now we can get started on building up the control.

The Template

Now that we have the files we need, we can add the template. This is straight forward, and we just add a new <ControlTemplate> to the ControlTemplate property:

<ContentPage ...
    xmlns:controls="clr-namespace:SkiaSharp.Extended.Controls"
    xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms">

    <controls:SKConfettiView>
        <controls:SKConfettiView.ControlTemplate>
            <ControlTemplate>
                <skia:SKCanvasView x:Name="PART_DrawingSurface" />
            </ControlTemplate>
        </controls:SKConfettiView.ControlTemplate>
    </controls:SKConfettiView>

</ContentPage>

So, let us have a look at all the moving parts in this XAML.

  1. First, there is the ControlTemplate property. This is just where we place the new template that we want to use for the control.
  2. Next, there is the <ControlTemplate> element. Just like with a data template, the actual views we want to add to the new control must go inside one of these.
  3. Now, there is <skia:SKCanvasView> element. This is just what we are going to use as our control. Not much now, but when a user overrides this template, they may want to wrap this is a frame to get a nice border.
  4. Finally, there is the x:Name="PART_DrawingSurface" attribute. This is what we will use to talk to the actual controls inside that we care about. In our control, we just care about the drawing surface, so we give that a name. If the user adds some cool frame, then we don’t need to worry about that.

As a demonstration of all this and a customization, I take this XAML (the red background is just so that we can see the surface):

<StackLayout>
    <Label Text="Plain control" Margin="20" />

    <controls:SKConfettiView Margin="20">
        <controls:SKConfettiView.ControlTemplate>
            <ControlTemplate>
                <skia:SKCanvasView x:Name="PART_DrawingSurface"
                                   BackgroundColor="Red" />
            </ControlTemplate>
        </controls:SKConfettiView.ControlTemplate>
    </controls:SKConfettiView>

    <Label Text="Custom control" Margin="20" />

    <controls:SKConfettiView Margin="20">
        <controls:SKConfettiView.ControlTemplate>
            <ControlTemplate>
                <Frame Padding="20">
                    <skia:SKCanvasView x:Name="PART_DrawingSurface"
                                       BackgroundColor="Red" />
                </Frame>
            </ControlTemplate>
        </controls:SKConfettiView.ControlTemplate>
    </controls:SKConfettiView>
</StackLayout>

And it renders like this:

Even though we have two different controls with two different view structures, we still have the same essential control because both have the core element in the template:

<skia:SKCanvasView x:Name="PART_DrawingSurface" />

The Code Behind

Because we are making a control that we actually want to do something, we need some code. To do this, we hop on over to our C# code file.

The way templated controls work is very similar to other controls, but with one additional feature – they allow the actual control to use a template. But, this means that anyone can go and put anything in that template. So, how do we get access to those views in the template? By listening for when the template is applied.

When a template is applied to a control, there is a method (OnApplyTemplate) that we can override and start to access the things in the template by name. For example, in our control template, we have a SkiaSharp SKCanvasView that is named PART_DrawingSurface. Now, in our code file, we can use the GetTemplateChild to get that child view:

public class SKConfettiView : TemplatedView
{
    protected override void OnApplyTemplate()
    {
        // get the child
        var templateChild = GetTemplateChild("PART_DrawingSurface");
        if (templateChild is SKCanvasView canvasView)
        {
            // subscribe to the paint even of the child so we can redraw
            canvasView.PaintSurface += OnPaintSurface;
        }
    }

    private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e)
    {
        e.Surface.Canvas.Clear(SKColors.Green);

        // TODO: draw the real thing
    }
}

When the framework determines it is time to build the actual control we see, it will invoke the OnApplyTemplate method, which we can then override to do things, such as subscribe to events or set properties. In our confetti control we are making, we just want to subscribe to the PaintSurface event and draw the confetti.

The GetTemplateChild method should only be called after the OnApplyTemplate method has been called.

If we run the code now, you can see that in both controls, the canvas has drawn a nice green background – even the one that has some weird frame around it! And this green is drawn from the event that we just subscribed to in the OnApplyTemplate method.

The Library

All done! Even though the confetti is not being drawn, our control is ready to package up. So, how do we do that? Again, very simple! We just create a new Xamarin.Forms class library and move the control there.

One this to remember is that when moving a control out of the main app project, we will have to update the XML namespaces and add the assembly= part:

<!-- from -->
xmlns:controls="clr-namespace:SkiaSharp.Extended.Controls"

<!-- to -->
xmlns:controls="clr-namespace:SkiaSharp.Extended.Controls;assembly=SkiaSharp.Extended.Controls"

Once the control is moved, we add a reference to this new library in our app, and make sure that it all works again.

However, if we package this library up and push to NuGet, every single developer out there will have to create their own control template. This is not how we want anyone to live! So, we ship our own template in the library!

The Resources

We could do a few things and place templates in a few places, but we want the control to use our default theme, but also allow for custom templates. So, in order to do this nicely, we can create a custom resource dictionary in our library. I decided to follow the pattern of UWP and WPF and place our “generic” control template in the “Themes\Generic.xaml” file.

Because there is no “resource dictionary” item template in Visual Studio, I just created a new XAML page and replaced the contents of both files.

In the XAML file, I specify the dictionary:

<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    xmlns:local="clr-namespace:SkiaSharp.Extended.Controls"
                    x:Class="SkiaSharp.Extended.Controls.Themes.Generic">
</ResourceDictionary>

In the C# code-behind, I change the base type:

public partial class Generic : ResourceDictionary
{
    public Generic()
    {
        InitializeComponent();
    }
}

Next, we need to move the template from the first control in our page into the resource dictionary XAML file. I went with three new entries:

  1. The new control template.
  2. The explicit style that applies that control template. This explicit style allows for extensions using the BasedOn property of styles.
  3. The implicit style that will apply our explicit style to all of the instances of our control.
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    xmlns:local="clr-namespace:SkiaSharp.Extended.Controls"
                    xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
                    x:Class="SkiaSharp.Extended.Controls.Themes.Generic">

    <!-- the control template for SKConfettiView -->
    <ControlTemplate x:Key="SKConfettiViewControlTemplate">
        <skia:SKCanvasView x:Name="PART_DrawingSurface" />
    </ControlTemplate>

    <!-- the explicit style that allows for extension -->
    <Style x:Key="SKConfettiViewStyle" TargetType="local:SKConfettiView">
        <Setter Property="ControlTemplate"
                Value="{StaticResource SKConfettiViewControlTemplate}" />
    </Style>

    <!-- the implicit style that applies to all controls -->
    <Style TargetType="local:SKConfettiView"
           BasedOn="{StaticResource SKConfettiViewDefaultStyle}" />

</ResourceDictionary>

This is a bit more XAML as we could have just created a single implicit style that also has the control template, but the multiple parts allow for multiple extension points and for reuse of parts if need be.

In order to test all this fancy new XAML, we can update our page to only provide a custom template for the first control:

<StackLayout>
    <Label Text="Plain control" Margin="20" />

    <controls:SKConfettiView Margin="20" />

    <Label Text="Custom control" Margin="20" />

    <controls:SKConfettiView Margin="20">
        <controls:SKConfettiView.ControlTemplate>
            <ControlTemplate>
                <Frame Padding="20">
                    <skia:SKCanvasView x:Name="PART_DrawingSurface" BackgroundColor="Red" />
                </Frame>
            </ControlTemplate>
        </controls:SKConfettiView.ControlTemplate>
    </controls:SKConfettiView>
</StackLayout>

When we run the app now, the first control is missing everything! What has happened? Is all lost? No! This is because the app does not know about this fancy new style we just created.

The Registration

There are a couple of ways to solve this. First we could just import the resource dictionary into the page or into the app. Because I want this style to apply to all parts of my app, I went with the app resources:

<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:themes="clr-namespace:SkiaSharp.Extended.Controls.Themes;assembly=SkiaSharp.Extended.Controls"
             x:Class="SkiaSharpDemo.App">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <themes:Generic />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

We are basically done now. No matter what we do, we are importing our styles and templates, and we also allow for total customization.

But.

We had to do work to get the styles to apply! We never want to do work. If we ship this out to NuGet, every single developer will forget to add the styles, we will get a new issue on our repository, we will be sad! No! We want magic!

In UWP and WPF, the path that we used for our XAML resources (Themes\Generic.xaml) is actually pretty special. So special in fact they have a docs page on this:

Theme-level dictionaries are stored in a subfolder named Themes. The files in the Themes folder correspond to themes. For example, you might have Aero.NormalColor.xaml, Luna.NormalColor.xaml, Royale.NormalColor.xaml, and so on. You can also have a file named Generic.xaml. When the system looks for a resource at the themes level, it first looks for it in the theme-specific file and then looks for it in Generic.xaml.

Now, it would be wonderful if Xamarin.Forms also was able to do something like this, wouldn’t it? Well, I agree! So I just opened an issue for this exact reason. I will try get it implemented.

But.

There is always a but! What about today? We can’t wait for some feature to ship! We need that confetti, now! We could throw up our hands and say “oh, well, ’tis what it is”. But we won’t! We come up with solutions!

The Hack

One way that seems to work just fine is to register the theme inside the control. And, we can do this by inserting our theme in the very same MergedDictionaries property that we just used.

Before we start hacking, we can remove that pesky code we just added to the App.xml and we will see our control disappear again. But not to worry, we will use magic to fix it.

This magic is pretty straight forward, in the Generic resource dictionary with out styles, we add a nice method to the code-behind:

public partial class Generic : ResourceDictionary
{
    private static bool registered;

    public Generic()
    {
        InitializeComponent();
    }

    internal static void EnsureRegistered()
    {
        // don't do extra work
        if (registered)
            return;

        // get the dictionary if we can
        var merged = Application.Current?.Resources?.MergedDictionaries;
        if (merged != null)
        {
            // check to see if we are added already
            foreach (var dic in merged)
            {
                if (dic.GetType() == typeof(Generic))
                {
                    registered = true;
                    break;
                }
            }

            // if we are not added, add ourselves
            if (!registered)
            {
                merged.Add(new Generic());
                registered = true;
            }
        }
    }
}

Finally, we can call this method in our control’s constructor:

public SKConfettiView()
{
    Generic.EnsureRegistered();
}

Only now we are done! We now have a very nice library that works automatically and is awesome for customization.

Who cares about the view anyway?

While working on an issue, I discovered a cool way in which to draw using SkiaSharp – without caring about view sizes at all.

In many cases, drawing code does not really care about the actual view sizes or canvas sizes. For example, if you are drawing a button, the drawing code is going to fill the entire view. If you are working on some image, you typically want the image to fill the view.

This is because in most cases, the UI framework will do all the view sizing based on your constraints, available space and any parameters. Then, you want to draw the best image on the size that the UI framework gave you.

Let’s take a practical example: we want to make a badge with a number on it.

Badge

If we assumed that the badge will always be 15×15, then we would think this would be easy. All our sizes would be around that number. But since we are drawing a circle from the center, we actually have a center of 7.5 and a radius of 7.5. This is not a problem in any way for SkiaSharp, but it is a bit for us as we now have more things to do.

If we were to draw this without checking screen density or actual view size, we might get something like this:

Tiny badge

This is because we have used numbers like 15 and 7.5. These numbers are actually tiny when compared to the thousands of pixels on modern devices.

If we used bigger numbers, this help, but not fix all the issues. For example, this might happen:

Too big Too small

This is a result of the way SkiaSharp and UI frameworks work. The way SkiaSharp does pixels is a bit different to typical UI frameworks. When designing a UI, the framework knows about screen densities so this typically means that UI frameworks will scale UI elements automatically.

For example, if there is a view with a size of 15×15, in most cases you would expect this view to be the same size across all screens and devices. So, if you were on an iPhone, this might translate to a 30×30 view. On some Android devices, they use a density of 3.5, so this translates to a 52.5. As a result of the screen density, placing the devices side by side results in very similar view sizes to our eyes.

However, SkiaSharp does not care about screen densities (maybe incorrectly, but that is for an open issue). Regardless of the device or platform, it asks the OS for the exact bounds of the view – in raw pixels. So, if we take our previous examples of iOS and Android, we will end up with different canvas sizes: 30×30 and a 52×52 (because there is no such thing as a .5 raster pixel).

Drawing Correctly

If we know that SkiaSharp does not scale automatically, we can use simple arithmetic to work out that we can just scale before we draw.

In all our drawing code examples, we are going to draw a 15×15 circle in the center of the view so that it touches the edges:

  // assume a perfect 15x15 canvas and view
  canvas.DrawCircle(7.5f, 7.5f, 7.5f, paint);
  

Screen Desnsity

To handle screen density, we could use something like Xamarin.Essentials. There is a nice DeviceDisplay API that will give us the main screen’s density:

// get the density
var density = (float)DeviceDisplay.MainDisplayInfo.Density;

// scale to the density
canvas.Scale(density);

// draw
canvas.DrawCircle(7.5f, 7.5f, 7.5f, paint);

This would work.

In that one case.

If we need to support devices where density may change or has multiple displays, then we can use a trick of just dividing the canvas size by the view size:

  var density = e.Info.Width / (float)this.Width;
  

NOTE: The e in the code above is from the event args of the PaintSurface event found on the various SkiaSharp views.

View Size

What happens if you decide that a 15×15 badge is too small and want to use 16×16 or even a big 20×20? Or, in a case where 15×15 is too big? You would think to just make the view bigger and all would be well.

Unfortunately, it won’t.

Because you may have used sizes like radius = 7.5f or a textSize = 8f.

Using exact sizes is often just fine, if you are very sure that the view size will never change. But, as developers, we can not assume that.

A smart developer might think to use the view size instead of hard coordinates. Then using arithmetic, scale things relative to that:

// get the density
var density = e.Info.Width / (float)this.Width;

// scale to the density
canvas.Scale(density);

// draw
var halfWidth = (float)this.Width / 2f;
canvas.DrawCircle(halfWidth, halfWidth, halfWidth, paint);

That would work.

In many cases.

If you have a lot of drawing to do, there may be many, many division and multiplication operations. Modern CPUs are very fast, but why even do that? Also, with every draw, you might end up with many other operations to calculate the size and position.

An example would be if padding was needed. If you were going for a 2px padding, then this would also have to be calculated:

var halfWidth = (float)this.Width / 2f;
var padding = 2f;
canvas.DrawCircle(halfWidth, halfWidth, halfWidth - (padding * 2), paint);

And this gets worse if you want the padding to be based on the circle size, maybe with a 10% padding:

var halfWidth = (float)this.Width / 2f;
var padding = (float)this.Width / 10f;
canvas.DrawCircle(halfWidth, halfWidth, halfWidth - (padding * 2), paint);

This involves lots of arithmetic – who really wants to deal with that when trying to draw a basic circle?

Not me.

Arbitrary Size

What if we could draw things using any base size, and then let the graphics engine do all the work? Like it was designed to do.

Now this is probably not something that I invented or discovered. I may have thought of it now, but I am not always the brightest person so that basically means everyone already knows. But, let’s assume that there was one other person that didn’t know.

So, what if we could take our 15×15 circle and convert that thought into a 100×100 circle and let the engine do the work to make our numbers appear as if it was 15×15?

We can do that with SkiaSharp.

It is called scaling. Pretty obvious, I know, but it only took a few years.

Instead of doing “advanced” arithmetic to calculate sizes, offsets and percentages, we can use any base size that makes things easier. In our example, we have a full-view circle with a number in the center.

So why not use 100 as the base size and have the circle have a radius of 50? Well, we can.

// pick a cool number for us
const float baseSize = 100f;

var canvas = e.Surface.Canvas;

// scale to our base unit
canvas.Scale(e.Info.Width / baseSize);

var circleFillPaint = new SKPaint {
    IsAntialias = true,
    Style = SKPaintStyle.Fill,
    Color = 0xFFFF5722,
};

// center of 50x50 and a radius of 50
canvas.DrawCircle(50f, 50f, 50f, circleFillPaint);

// we can even use nice numbers for font sizes
var textPaint = new SKPaint {
    IsAntialias = true,
    TextSize = 70f,
    Color = SKColors.White,
};

// measure the text width
var textBounds = SKRect.Empty;
var advance = textPaint.MeasureText(BadgeValue, ref textBounds);

// draw the text at the center (x = 50 - half the width; y = 100 - half text height)
canvas.DrawText(BadgeValue, 50f - (advance / 2f), 100f - (textBounds.Height / 2f), textPaint);

Now, we can use this exact code to render a perfect badge, regardless of the view size, the screen density or any other view-related property. The reason for this is that the first thing we do is convert from drawing units into our perfect unit:

canvas.Scale(e.Info.Width / baseSize);

As long as our numbers are based on baseSize, then we can never go wrong.

Beware of C# 8 Using Statements

Let’s be honest here, C# 8 is crazy cool. It has such a big set of new features to make developers more productive and write even better code. There are some awesome things, like nullable reference types and asynchronous streams (async enumerables). There are also some weird things, like private members on interfaces. But there are many features that just make life better. Using statements is one of them.

If you want to see a list of all the new things, check out the Microsoft docs. It has all the goodness.

But, let’s get back to the using statements. What are they? Where are they used? Well, using statements are just normal using blocks with some syntactic sugar to make the code more readable. Here is an example of a normal, traditional using block:

using (var stream = File.Create("test.txt"))
using (var writer = new StreamWriter(stream))
{
    writer.Write("Hello World!");
}

This is a very simple example. There are two objects that need to be disposed, and we have them in the using blocks. This code creates a file, creates a writer and then writes to the file. At the end, the writer closes the stream and the file is closed. We have all seen this before.

So, what does C# 8 bring to the table? Well, lets convert the using block into a using statement:

using var stream = File.Create("test.txt");
using var writer = new StreamWriter(stream);

writer.Write("Hello World!");

It is very similar, but there are no braces and parenthesis. There are no indents.

The Good

That was a simple example, but just imagine the case where there are loops, conditions and other statements. It could, and does, get a bit messy. Take a look at this example:

var array = new[] { "first", "second", "third" };
foreach (var item in array)
{
    using (var stream = File.Create($"{item}.txt"))
    {
        stream.WriteByte(1);
        if (item != null)
        {
            using (var writer = new StreamWriter(stream))
            {
                writer.Write("Hello World!");
            }
        }
    }
}

Lots of nesting, lots of indents, lots of braces. With using statements we can remove 4 lines and 2 levels of indents. Much better on the eyes:

var array = new[] { "first", "second", "third" };
foreach (var item in array)
{
    using var stream = File.Create($"{item}.txt");
    stream.WriteByte(1);
    if (item != null)
    {
        using var writer = new StreamWriter(stream);
        writer.Write("Hello World!");
    }
}

The Bad

We saw a nice saving of everything, so what is this “beware” in the title? Well, it has to do with scopes. The using statements are nice as they dispose/close things when they go out of scope.

If we look at the example above, we can see the stream variable goes out of scope at the end of each iteration of the foreach loop. This means that after the code in the foreach block runs, it is auto disposed. That is nice. But, this is also the cause of the “beware”. Take a look at this example:

using (var stream = File.Create("test.txt"))
using (var writer = new StreamWriter(stream))
{
    writer.Write("Hello World!");
}

return File.ReadAllText("test.txt");

Here, we create a file, write to it, dispose it and then return the results. We probably wouldn’t write this exact code in real life, but hey, examples! If we were to convert this into using statements, as one would be tempted, we end up with this code:

using var stream = File.Create("test.txt");
using var writer = new StreamWriter(stream);

writer.Write("Hello World!");

return File.ReadAllText("test.txt");

That looks nice, but has a “hidden” bug. If you think back to the using statements and their scope… Where does the stream go out of scope? At the end of the method, after the return. So what does this mean? Well, it is that the stream is still open and the file handle is being held. That means we will get an exception:

Unhandled exception. System.IO.IOException:
The process cannot access the file ‘test.txt’ because it is being used by another process.

Not so nice.

We can have a look at what the compiler writes to help us understand what just happened:

using (var stream = File.Create("test.txt"))
using (var writer = new StreamWriter(stream))
{
    writer.Write("Hello World!");

    return File.ReadAllText("test.txt");
}

As you can see, the return is inside the using block.

Not what we wanted.

The Ugly

Just when we thought we had the bad news, there is more. An exception is not nice, but at least we know something went wrong. We can fix that. So what is worse than an unhandled exception? No exception!

If our operating system was cool with opening a file that was already opened. We cannot be sure that the contents had actually been flushed! Some streams only flush when the stream is either explicitly flushed or when it is closed.

So, if we are running on this system, we would not get an exception, but we would return an empty string. Even though we just wrote to the file! This is most certainly an unexpected result!

Now, streams are one thing and we can handle that. But it gets tricky when we have other disposable objects.

Maybe they are very large. If we have 1GB of RAM and we open a 1GB file, we are good. But if we try an open another 1GB file, we will run out of memory. If we were using blocks, then we could control the fact that it had to first close the first file before opening the second.

Maybe they are critical. We could potentially lock some resource for longer than necessary if we aren’t careful. This is very dangerous. We could potentially cause other systems of functions to crash because things took too long to respond.

At the end of the day. Use the new using statements. Your code will be better. But… Use them were they should be used. Don’t just auto-convert all blocks to statements with ReSharper.

Turning Events into Commands

Have you ever used some control in Xamarin.Forms that appears to have an event instead of a command? You are working the MVVM love and then you come across that annoying control. Almost all the Xamarin.Forms controls have both events and commands, enabling choice, but you do get those non-conforming ones…

I was lurking on the Xamarin forums and I came across a question regarding the event-only design of the SkiaSharp SKCanvasView. The SKCanvasView has a PaintSurface event that allows you to draw on the view with SkiaSharp commands.

There is nothing wrong with the event as it stands, but things get messy when all the data is in a view model. In simple cases, this is easy to resolve. Take a small example where there is only one view model, which is the binding context for an entire Page:

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();

        BindingContext = new MainViewModel();
    }
}

And the view model looks like this:

public class MainViewModel
{
    public MainViewModel()
    {
        PaintCommand = new Command<SKPaintSurfaceEventArgs>(OnPainting);
    }

    public ICommand PaintCommand { get; private set; }

    private void OnPainting(SKPaintSurfaceEventArgs e)
    {
        // ... draw ...
    }
}

Where, or rather how, does one get an event somewhere on the page to the view model? Well, one way would be to attach a handler to the view and then pass the event arguments to the view model:

canvasView.PaintSurface += (sender, e) =>
{
    // we can do this because of our simple example
    var viewModel = (MainViewModel)BindingContext;

    // fire the command
    if (viewModel.PaintCommand.CanExecute(e))
    {
        viewModel.PaintCommand.Execute(e);
    }
};

This will work as everything is pretty much straight-forward. However, what happens if the canvas is in a ListView or if there are several canvases on the page? We would end up with a messy code-behind and probably a few memory leaks.

A much better way to solve this problem would be to use Xamarin.Forms’ behaviors:

Behaviors lets you add functionality to user interface controls without having to subclass them. Behaviors are written in code and added to controls in XAML or code.

Behaviors are easy to create and easy to use. The first thing we need to do is create our specific behavior:

public class PaintSurfaceCommandBehavior : Behavior<SKCanvasView>
{
    // we need a bindable property for the command
    public static readonly BindableProperty CommandProperty =
        BindableProperty.Create(
            nameof(Command),
            typeof(ICommand),
            typeof(PaintSurfaceCommandBehavior),
            null);

    // the command property
    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    // invoked immediately after the behavior is attached to a control
    protected override void OnAttachedTo(SKCanvasView bindable)
    {
        base.OnAttachedTo(bindable);

        // we want to be notified when the view's context changes
        bindable.BindingContextChanged += OnBindingContextChanged;
        // we are interested in the paint event
        bindable.PaintSurface += OnPaintSurface;
    }

    // invoked when the behavior is removed from the control
    protected override void OnDetachingFrom(SKCanvasView bindable)
    {
        base.OnDetachingFrom(bindable);

        // unsubscribe from all events
        bindable.BindingContextChanged -= OnBindingContextChanged;
        bindable.PaintSurface -= OnPaintSurface;
    }

    // the view's context changed
    private void OnBindingContextChanged(object sender, EventArgs e)
    {
        // update the behavior's context to match the view
        BindingContext = ((BindableObject)sender).BindingContext;
    }

    // the canvas needs to be painted
    private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e)
    {
        // first check if the command can/should be fired
        if (Command?.CanExecute(e) == true)
        {
            // fire the command
            Command.Execute(e);
        }
    }
}

Now that we have the behavior, we can simply add it to the canvas view:

<views:SKCanvasView>
    <views:SKCanvasView.Behaviors>
        <local:PaintSurfaceCommandBehavior Command="{Binding PaintCommand}" />
    </views:SKCanvasView.Behaviors>
</views:SKCanvasView>

That’s it! Our canvas is now command-based and can be drawn on from the view model.

This is just a very limited behavior, for one specific event for one specific view. But, behaviors are very powerful and can be used to do many more things. One such use is to make a more generic behavior that can map any event to any command:

Besides those examples, be sure to read more about behaviors, and what they can do, in the Xamarin documentation.

Evolution of the NuGet PackageReference

NuGet is probably the best thing that happened to .NET dependencies. Before this great time, we all had to copy or worse, commit a bunch of assemblies into source control – just so we could build our projects. And for library developers… well, we had to find someone to host our libraries.

When NuGet was born, we could just throw our libraries up on nuget.org and be done with it. We could tweet about it and then anyone could open the package manager and click install. The repository stayed binary-free and the library started growing in users. Great for everyone.

Both NuGet and MSBuild have evolved much over time, and there have been a few different incarnations of the simple, but complex, feature of including a NuGet package into the project file. It took a few tries, but we are at the best so far with PackageReference. But, before we get there, let us recap some of the past ideas…

packages.config

There was a downside to the first NuGet: it scratched around in your .csproj and added a few elements that sometimes got mixed up. Let’s take a simple project, and add SkiaSharp:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  ...
  <ItemGroup>
    <Reference Include="SkiaSharp">
      <HintPath>..\packages\SkiaSharp.1.58.1\lib\net45\SkiaSharp.dll</HintPath>
    </Reference>
  </ItemGroup>
  ...
  <ItemGroup>
    <None Include="packages.config" />
  </ItemGroup>
  ...
  <Import Project="..\packages\SkiaSharp.1.58.1\build\net45\SkiaSharp.targets" Condition="Exists('..\packages\SkiaSharp.1.58.1\build\net45\SkiaSharp.targets')" />
  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
    <PropertyGroup>
      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
    </PropertyGroup>
    <Error Condition="!Exists('..\packages\SkiaSharp.1.58.1\build\net45\SkiaSharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\SkiaSharp.1.58.1\build\net45\SkiaSharp.targets'))" />
  </Target>
</Project>

Our beautiful project file just got a bit mutilated… Still, it is not that bad, right? Well, what happens if you use a few packages? You get a project file that has quite a few elements that basically pull in a bunch of assemblies and add a few targets – there is just clutter.

Although this is all correct MSBuild file, the packages are really managed by that packages.config file. The IDE and NuGet use that file to track the installed packages and also to update the project file with the assembly references and target imports.

You can read more about the packages.config file here.

project.json

Along came a spider (named .NET Core) and sat down besIDE her…

The guys working on .NET Core also had had enough of this, (they may have gone a bit too far and removed all XML) so they came up with project.json. Although they threw the .csproj right out of the window, they had a cool idea when it came to NuGet packages: don’t touch the project file.

Initially, project.json was just for ASP.NET Core apps, but they also used it for (and still do) UWP apps. Then, they decided to let other project types use it. If we were to install the SkiaSharp package into a project.json file, we would end up with something like this:

{
  "dependencies": {
    "SkiaSharp": "1.58.1"
  },
  "frameworks": {
    "net46": { }
  },
  "runtimes": {
    "win": { }
  }
}

This WAS way neater than the big, clunky .csproj, and – best of all – NuGet managed itself. No need for assembly references and importing .targets. Also, because NuGet never touched the .csproj, it could never get it wrong.

The downside to project.json was simply the fact that it was no longer MSBuild. There were other project types, such as .xproj that would pull in the project.json and then make it work with MSBuild, but now we have even more files and overhead. The problem of less was undone by the new file type.

You can read more about the project.json file here.

PackageReference

So, the experts got together and decided to come up with a plan – a format to rule them all. They took the idea that NuGet needs to be MSBuild and that it must not touch what it shouldn’t. It needs to be minimal, but still powerful.

This is what they came up with:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  ...
  <ItemGroup>
    <PackageReference Include="SkiaSharp" Version="1.58.1" />
  </ItemGroup>
  ...
</Project>

No, your browser is not still loading. That simple, single line does it all. There is no additional packages.config or project.json file. That goes directly in the .csproj like any .NET framework reference (such as when including System.IO.Compression).

I could write a big puff piece about how awesome this is, but the whole point is to not have that puff. I really love this new format, and I hope that you will too. I have tested this with many projects, including Xamarin projects. It all works, and it should – it is part of MSBuild, and Xamarin uses MSBuild. This is one of the cool features about having a MSBuild-based project: if MSBuild supports it, then so does your project.

You can read more about the PackageReference format here. And, there is some more information about using PackageReference in any project type here.

Requirements

Using this new PackageReference format makes life so much easier, but there are some things that you will need before you switch over all those projects:

  • MSBuild v15
  • NuGet v4.x

If you want to use an IDE, the best still are:

  • Visual Studio 2017
  • Visual Studio for Mac v7.1

The current set of requirements is just that you need to be using MSBuild v15 (comes with Visual Studio) and NuGet v4.x (also comes with Visual Studio). If you need the NuGet command line tool, you can get it here.

By default, Visual Studio will use the packages.json format, but you can change this in the options. Navigate to “Tools” > “Options…”, then “NuGet Package Manager” > “General”:

NuGet Package Manager

See more information about using PackageReference in any project type here.

Limitations

Right now this magic works on Windows and macOS without anything special. Linux is a bit different… As it has a case-sensitive file system, and NuGet is a little inconsiderate: it downloads the packages as lowercase, but then tries to include the real case.

If you look at the ~/.nuget/packages directory, you will see a skiasharp directory, but when you try and compile, you will get this error:

error : The package SkiaSharp with version 1.58.1 could not be found in /home/matthew/.nuget/packages/. Run a NuGet package restore to download the package.

Exciting stuff! But no worries, until NuGet/MSBuild fixes this, we can just tell Mono to ignore case sensitivity using the MONO_IOMAP environment variable:

> export MONO_IOMAP=all
> msbuild

Or:

> MONO_IOMAP=all msbuild

That was mostly painless. Still, we can set that environment variable per build and not affect any other apps. And, this is just a tiny bit of “work” so that we can get really awesome, clean .csproj files.

So, is there anything stopping you from using the PackageReference in your projects? No! Transition Now!

Multi-Select ListView

I was just hanging around in the IDE this week and I had a chat with ListView. He was a very nice guy, but he was complaining about the fact that for some reason he could only ever select one item at a time…

I think of myself as a somewhat decent coder, and I decided to solve this problem – at least some part of it.

The easiest, and quickest, way to add multi-select capabilities to a ListView requires two steps: the “selectable” item and the “select” action.

The Selectable Item

I started with the model:

public class SelectableItem
{
    public object Data { get; set; }
    public bool IsSelected { get; set; }
}

But, since we are doing data binding, I created a bindable object that has several bindable properties:

public class SelectableItem : BindableObject
{
    public static readonly BindableProperty DataProperty =
        BindableProperty.Create(
            nameof(Data),
            typeof(object),
            typeof(SelectableItem),
            (object)null);

    public static readonly BindableProperty IsSelectedProperty =
        BindableProperty.Create(
            nameof(IsSelected),
            typeof(bool),
            typeof(SelectableItem),
            false);

    public SelectableItem(object data)
    {
        Data = data;
        IsSelected = false;
    }

    public SelectableItem(object data, bool isSelected)
    {
        Data = data;
        IsSelected = isSelected;
    }

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    public bool IsSelected
    {
        get { return (bool)GetValue(IsSelectedProperty); }
        set { SetValue(IsSelectedProperty, value); }
    }
}

You may have noticed that I didn’t create a generic type. This is because later on we are going to want to get the value of the IsSelected property from the ItemSelected event handler, and we won’t know what the type is. However, we can create a generic type that inherits from this base type:

public class SelectableItem<T> : SelectableItem
{
    public SelectableItem(T data)
        : base(data)
    {
    }

    public SelectableItem(T data, bool isSelected)
        : base(data, isSelected)
    {
    }

    // this is safe as we are just returning the base value
    public new T Data
    {
        get { return (T)base.Data; }
        set { base.Data = value; }
    }
}

We now have a nice generic type for the developer (us) and a non-generic type for the event (the machine).

The Selectable ListView

The next step is to hook up the ListView with the selectable items. So, we will need a data field on the view model or the Page – depending on how you work (note the generic SelectableItem):

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();

        Items = new ObservableCollection<SelectableItem<string>>();

        BindingContext = this;
    }

    public ObservableCollection<SelectableItem<string>> Items { get; }
}

And, we need a list item that has a “checked” state (here it is just a red block):

<ListView ItemsSource="{Binding Items}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Orientation="Horizontal">
                    <!-- the "check" mark -->
                    <BoxView IsVisible="{Binding IsSelected}" 
                             WidthRequest="12" HeightRequest="12"
                             Color="Red" />
                    <!-- the text/data -->
                    <Label Text="{Binding Data}" />
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

We should now have a list of items that can show either a selected or unselected state. To handle when an item is selected by the user, we just need an event on the list:

<ListView ... ItemSelected="OnItemSelected">
    ...
</ListView>

And then we write the code to toggle the selection (note the non-generic SelectableItem):

private void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
    var item = e.SelectedItem as SelectableItem;
    if (item != null)
    {
        // toggle the selection property
        item.IsSelected = !item.IsSelected;
    }

    // deselect the item
    ((ListView)sender).SelectedItem = null;
}

This is all we need, and we will have a ListView that that can support multiple items being selected.

Improvements

We could call it a day, but we are not going to. The day has just started, and we are thinking that we might want to use this in multiple places. We can just copy the logic – mainly the event and cell view, but there are better ways (and we don’t like duplicate code).

Attached Property

The first thing that we will look at is if we can magically do the event hookup with a single property instead of the event:

<ListView ... local:MultiSelectListView.IsMultiSelect="True">
    ...
</ListView>

That looks nicer than the event, and we have a couple of benefits: no code in the page, the event code is written once and the property is bindable.

What we are doing here is using an attached property to “inject” a bindable property into an existing view type:

public static class MultiSelectListView
{
    public static readonly BindableProperty IsMultiSelectProperty =
        BindableProperty.CreateAttached(
            "IsMultiSelect",
            typeof(bool),
            typeof(ListView),
            false,
            propertyChanged: OnIsMultiSelectChanged);

    public static bool GetIsMultiSelect(BindableObject view)
        => (bool)view.GetValue(IsMultiSelectProperty);

    public static void SetIsMultiSelect(BindableObject view, bool value)
        => view.SetValue(IsMultiSelectProperty, value);

    private static void OnIsMultiSelectChanged(
        BindableObject bindable, object oldValue, object newValue)
    {
        var listView = bindable as ListView;
        if (listView != null)
        {
            // always remove event
            listView.ItemSelected -= OnItemSelected;

            // add the event if true
            if (true.Equals(newValue))
            {
                listView.ItemSelected += OnItemSelected;
            }
        }
    }

    private static void OnItemSelected(
        object sender, SelectedItemChangedEventArgs e)
    {
        var item = e.SelectedItem as SelectableItem;
        if (item != null)
        {
            // toggle the selection property
            item.IsSelected = !item.IsSelected;
        }

        // deselect the item
        ((ListView)sender).SelectedItem = null;
    }
}

We now have a super easy way to turn any list into a multi-select list with a single property.

The ItemsSource

Another area we can improve is the ItemsSource collection. Right now we have quite a long type with two generic types:

public ObservableCollection<SelectableItem<string>> Items { get; }

We can not only make this shorter, but more convenient by creating a new type that derives from ObservableCollection. And, now that we have a new type, we can add additional methods so that we don’t even have to deal with the SelectableItem type at all:

public class SelectableObservableCollection<T> : ObservableCollection<SelectableItem<T>>
{
    ...

    // a constructor overload
    public SelectableObservableCollection(IEnumerable<T> collection)
        : base(collection.Select(c => new SelectableItem<T>(c)))
    {
    }

    ...

    // a convenience property
    public IEnumerable<T> SelectedItems
        => this.Where(i => i.IsSelected).Select(i => i.Data);

    ...

    // a method overload
    public void Add(T item)
    {
        Add(new SelectableItem<T>(item));
    }
}

When we use this new type, we can do some cool things:

// a nice type
public SelectableObservableCollection<string> Items { get; }

// cool methods and properties
private void OnDoSomething()
{
    Debug.WriteLine("You have selected:");

    // use a property
    foreach (var selected in Items.SelectedItems)
    {
        Debug.WriteLine($" - {selected.Data}");
    }

    // use a method
    Items.Add("A New String");
}

The Cell

Finally, as you may have a really cool check mark for selected items (unlike our red block now), we will want to be able to create a custom cell type that will allow us to just specify the item contents, and automatically handle the check mark:

<ListView ItemsSource="{Binding Items}"
          local:MultiSelectListView.IsMultiSelect="True">
    <ListView.ItemTemplate>
        <DataTemplate>
            <local:SelectableViewCell>
                <Label Text="{Binding}" />
            </local:SelectableViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

This requires a new Cell type:

[ContentProperty(nameof(DataView))]
public class SelectableViewCell : ViewCell
{
    public SelectableViewCell();

    public View CheckView { get; set; }

    public View DataView { get; set; }
}

I have left the implementation of this cell to your imagination… just kidding, I have it all in my my repository. You can find all this code, a sample app and more there too:

I hope you enjoyed this short(ish) post and are able to make your list views handle the selection of multiple items.

Embedding Xamarin.Forms in Native Apps

Xamarin.Forms is really cool! It allows you to almost write your app once and then compile for many platforms. With Xamarin.Forms, you can quickly produce multiple apps, but, you can also take advantage of some awesome features – such as cross-platform UIs in XAML, data binding, sharing code and much more.

Xamarin.iOS, Xamarin.Android and UWP are also fantastic! You can get 100% of the platform APIs and you can produce apps that are super fast and polished.

Most of the time you have to choose between one or the other. Sure, you can do custom renderers or effects in Xamarin.Forms to get more platform API access. And sure, you can use frameworks that help you share code with native Xamarin and Windows apps. Before today, you had one of two choices:

  • Xamarin.Forms for 100% shared code and UI
  • Xamarin/Windows Native for polished, platform-specific APIs and UIs

But… why not have both? Recently Xamarin/Microsoft shared on the blog that Xamarin.Forms can be embedded into native apps. This means that you can take your existing (or new) native app and just drop in a Xamarin.Forms page without doing anything special. You lose nothing, and gain a whole lot more. You can still use XAML, data binding, converters, effects and everything else that comes with Xamarin.Forms – but now from within you native app code and UI.

I have a nice sample app that you can pull from GitHub. Be sure to check it out and let me know what you think of this new functionality. I will try and keep that repository up to date with any new developments.

Xamarin.Forms embedded in native apps

Getting the Bits

To embed Xamarin.Forms into your native app, you just need to install a preview NuGet from the Xamarin.Forms pre-release feed:

https://www.myget.org/F/xamarinforms-dev/api/v3/index.json

Then, you want to install the 3.0.0.100-embeddingpreview NuGet into any Xamarin.Forms projects as well as into the native app projects.

That is it! Now you should be able to create your shared page.

If you have any questions or comments you can do this using the Xamarin discussion (Preview: Xamarin.Forms Embedding) on the forums.

It is important to note that this is a pre-release and functionality may change with subsequent releases.

Creating Shared Pages

Let’s take an example of an existing app that you want to add the ability to register and/or login to save user preferences on some cloud service – such as Azure. Your app is out and in the wild, users are loving it, and, you have just received feedback that they want to login across devices and keep their preferences.

What do you do? Well you could create a few screens for each platform and then share some code. But, as all the login screens are going to look the same and work the same, why not do everything in shared XAML?

So, the first thing we can do is to either create a shared project, a .NET Standard library or even a PCL. We then just need to install the pre-release Xamarin.Forms NuGet. Finally, we can go ahead an add a new XAML page. Just right-click and do “Add” > “New Item…” > “Content Page (XAML)” and then you have a new page.

In this page below, I am using data binding, converters, resource dictionaries and good old XAML markup:

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:app="clr-namespace:EmbeddedFormsDemo.Converters"
             x:Class="EmbeddedFormsDemo.Views.LoginPage">
    <ContentPage.Resources>
        <ResourceDictionary>
            <app:NegateConverter x:Key="Negate" />
            <app:NullInvisibilityConverter x:Key="NullInvisibility" />
        </ResourceDictionary>
    </ContentPage.Resources>
    <ScrollView>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <StackLayout Spacing="12" Grid.Row="1">
                <StackLayout.Padding>
                    <OnPlatform x:TypeArguments="Thickness" 
                                Android="24" iOS="24" WinPhone="0" />
                </StackLayout.Padding>
                <Label Text="Enter any username/password:"
                       HorizontalTextAlignment="Center"
                       FontSize="12" />
                <Entry Keyboard="Email" 
                       Placeholder="username or email"
                       Text="{Binding UserName}" 
                       HorizontalTextAlignment="Center"
                       IsEnabled="{Binding IsBusy, Converter={StaticResource Negate}}" />
                <Entry IsPassword="True" 
                       Placeholder="password" 
                       Text="{Binding Password}" 
                       HorizontalTextAlignment="Center"
                       IsEnabled="{Binding IsBusy, Converter={StaticResource Negate}}" />
                <Button Text="Log In" 
                        Command="{Binding LoginCommand}"
                        IsEnabled="{Binding IsBusy, Converter={StaticResource Negate}}" />
                <Label Text="{Binding ErrorMessage}" 
                       HorizontalTextAlignment="Center"
                       FontSize="12"
                       TextColor="Red" 
                       IsVisible="{Binding ErrorMessage, Converter={StaticResource NullInvisibility}}" />
                <ActivityIndicator IsRunning="{Binding IsBusy}" 
                                   IsVisible="{Binding IsBusy}" />
            </StackLayout>
        </Grid>
    </ScrollView>
</ContentPage>

Then, in our code-behind, we can write out code to work with the UI. Here we have made use of several features such as binding, commands, messaging and async/await:

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class LoginPage : ContentPage
{
    public const string LoginMessage = "login";

    private readonly JsonPlaceholderApi api;
    private string errorMessage;

    public LoginPage()
    {
        InitializeComponent();

        // initialize our fake services
        api = new JsonPlaceholderApi();

        // set up the data binding
        LoginCommand = new Command(OnLogin);
        BindingContext = this;
    }

    private async void OnLogin()
    {
        IsBusy = true;

        // reset errors
        ErrorMessage = "";
        // try logging in with our fake services
        var user = await api.LoginAsync(UserName, Password);
        if (user == null) {
            // there was an error
            ErrorMessage = "There was a problem logging in.";
        } else {
            // let the app know we are finished
            MessagingCenter.Send(user, LoginMessage);
        }

        IsBusy = false;
    }

    public string ErrorMessage
    {
        get { return errorMessage; }
        set { errorMessage = value; OnPropertyChanged(); }
    }

    // we don't want to save this as the user types
    public string UserName { get; set; }

    // we don't want to save this at all
    public string Password { get; set; }

    // the login button uses this
    public ICommand LoginCommand { get; }
}

That is basically all we need to do in order to create our UI. The JsonPlaceholderApi type just makes use of http://jsonplaceholder.typicode.com to get some random data, the User type is just a simple POCO object and the converters are basic IValueConverter implementations.

Displaying Shared Pages in Native Apps

Once we have created our shared Xamarin.Forms page, we can just instantiate out Xamarin.Forms page and then ask for the native version.

On Android, the CreateFragment extension method will return a native Android Fragment, which we can then use as we would any other fragment. On iOS, we use the CreateViewController extension method and we will get out a native UIViewController that, again, we can use as we would any other view controller. And finally, on Windows, we use the CreateFrameworkElement extension method to get out a native FrameworkElement that we can also uses as any other element.

There are two steps to obtaining this native container, first we make sure Xamarin.forms is initialized:

// Android
Xamarin.Forms.Forms.Init(this, null);

// iOS
Xamarin.Forms.Forms.Init();

// Windows
// the `e` from `Application.OnLaunched(LaunchActivatedEventArgs e)`
Xamarin.Forms.Forms.Init(e);

Once that is done, we can then get the native page:

// create the Xamarin.Forms page for all platforms
var formsPage = new MyFormsPage();

// Android - get the native Fragment
var nativeFragment = formsPage.CreateFragment(this);

// iOS - get the native UIViewController
var nativeController = formsPage.CreateViewController();

// Windows - get the native FrameworkElement
var nativeElement = formsPage.CreateFrameworkElement();

Now that we have the native view, we can just go ahead and use it as if it was created using the traditional mechanisms.

Xamarin.Android and Xamarin.Forms

When using Xamarin.Forms with an Android app, we are going to need to handle the native Fragment that represents the page. To this end, our Android app is using a native .axml layout with a FrameLayout that will hold all our fragments:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <!-- the other bits of UI -->
    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/frameLayout" />
    <!-- some more UI -->
</RelativeLayout>

Then, in our main activity code, we load this UI as normal and everything works as it usually does. When we want to show our new XAML page at some point, all we need to do is to just make sure Xamarin.Forms is initialized and then instantiate the page before navigating to it:

using Xamarin.Forms.Platform.Android;

public void DisplayLogin()
{
    if (!Xamarin.Forms.Forms.IsInitialized)
    {
        // initialize Xamarin.Forms before we use it
        Xamarin.Forms.Forms.Init(this, null);

        // we want to listen to the messaging center
        Xamarin.Forms.MessagingCenter.Subscribe(this, LoginPage.LoginMessage, (User user) =>
        {
            // update the app
            CurrentUser = user;

            // go back to the main page
            FragmentManager.PopBackStack();
        });
    }

    // create the login page (Xamarin.Forms ContentPage)
    var loginPage = new LoginPage();

    // get hold of the native Android fragment that represents the Xamarin.Forms page
    var loginFragment = loginPage.CreateFragment(this);

    // show the login screen (native Xamarin.Android)
    FragmentManager
        .BeginTransaction()
        .AddToBackStack(null)
        .Replace(Resource.Id.frameLayout, loginFragment)
        .Commit();
}

Xamarin.iOS and Xamarin.Forms

If we want to use Xamarin.Forms in our iOS app, we will be showing a new UIViewController. We first need to make sure that Xamarin.Forms is initialized and then we can just go ahead and create the desired page. We then get the native view controller that can be presented using all the existing means:

using Xamarin.Forms;

partial void OnLoginClicked(UIButton sender)
{
    if (!Xamarin.Forms.Forms.IsInitialized)
    {
        // initialize Xamarin.Forms before we use it
        Xamarin.Forms.Forms.Init();

        // we want to listen to the messaging center
        Xamarin.Forms.MessagingCenter.Subscribe(this, LoginPage.LoginMessage, (User user) =>
        {
            // update the app
            User = user;

            // go back to the main page
            NavigationController.PopViewController(true);
        });
    }

    // create the login page (Xamarin.Forms ContentPage)
    var loginPage = new LoginPage();

    // show the login screen
    var viewController = loginPage.CreateViewController();
    NavigationController.PushViewController(viewController, true);
}

Windows UWP and Xamarin.Forms

When we want to show a Xamarin.Forms page within our native UWP app, we will work with a FrameworkElement. Like with all the other platforms, we have to make sure that Xamarin.Forms is initialized and then just create the page. Once we have obtained the native element, we can just place it anywhere we need it to be. In this example, I am placing my view in a Flyout as the it is being opened:

using Xamarin.Forms;

private void OnLoginFlyoutOpening(object sender, object e)
{
    var flyout = sender as Flyout;

    if (!Xamarin.Forms.Forms.IsInitialized)
    {
        // initialize Xamarin.Forms before we use it
        Xamarin.Forms.Forms.Init(App.LastLaunchEventArgs);

        // we want to listen to the messaging center
        Xamarin.Forms.MessagingCenter.Subscribe(this, LoginPage.LoginMessage, (User user) =>
        {
            // update the app
            User = user;
            // show some message for some random reason
            WelcomeText = $"Welcome back {user.Name}!";

            // hide the login screen
            flyout.Hide();
        });
    }

    // create the login page (Xamarin.Forms ContentPage)
    var loginPage = new LoginPage();

    // set the native dialog to contain the shared login
    var loginElement = loginPage.CreateFrameworkElement();
    flyout.Content = new Frame
    {
        Content = loginElement,
        Width = 300,
        Height = 200
    };
}

Summary

In this fairly long post, we looked at how to quickly embed a Xamarin.Forms page into an existing native app. The process is easy and painless, and will only get better.

You can download the full code from my GitHub repository and try it out for yourself. And maybe have a look at your app and see if some of those screens that are exactly the same could use Xamarin.Forms.

You can also check out some links:

Some other people also have blogs:

And, then there is code:

Powershell & VCVars Batch

Recently, I have been doing more and more work with PowerShell, which is a very good thing. PowerShell is far more powerful than the “classic” batch files, and one of the feature I love is the ability to use the .NET framework right in there.

The downside for development is the fact that Visual Studio environments are not set properly. Typically, I would start the Visual Studio command prompt and then launch PowerShell. This works most of the time as I typically only build one platform.

But, doing a bit of research, I found that I can run the vcvars batch file, and then get a list of all the environment variables. Thanks to Niclas Lindgren and Chris Tavares, I merged and modified their scripts into this small function that allows PowerShell to set up its environment as if vcvars was run. Another big thing is that you can change the environment halfway through, such as if you are building for both x86 and x64.

function VsVarsAll($version = "14.0", $platform = "x86") {
    # handle 64-bit OS differences
    $64bit = !(gv PSHOME).Value.ToLower().Contains("syswow64")
    $HKLM = "HKLM:\SOFTWARE"
    if ($64bit) {
        $HKLM = "HKLM:SOFTWARE\Wow6432Node"
    }

    # get the path to vcvarsall.bat
    $VsRoot = (gp "$HKLM\Microsoft\VisualStudio\$version").ShellFolder
    $file = [System.IO.Path]::Combine($VsRoot, "VC", "vcvarsall.bat")

    # run the .bat, and return a list of all the envvars
    $cmd = "`"$file`" $platform & set"
    cmd /c $cmd | Foreach-Object {
        # parse the variables, and set them in powershell
        $p, $v = $_.split('=')
        Set-Item -path env:$p -value $v
    }

    # cool factor: update the title
    [System.Console]::Title = "VS $version - $platform Windows PowerShell"
}

To set up for x86 development, just run:

VsVarsAll -platform "x86"

Similarly, for x64:

VsVarsAll -platform "x64"

If you are running an older/newer Visual Studio, you can set the version:

VsVarsAll -version = "14.0" -platform "x86"

Xamarin.Android Binding Generators

UPDATE

This NuGet is no longer required to get nice parameter names in the binding. With the release of Cycle 8, Xamarin has provided a way to use the class-parse tool that comes with the Xamarin release.

More information can be found on the binding docs, but the gist of it is that you just need to add a new element to your project file:

<PropertyGroup>
  <AndroidClassParser>class-parse</AndroidClassParser>
</PropertyGroup>


Build status

A MSBuild Task to make Xamarin.Android binding projects easier.

Currently, there is no nice way to set the parameter names for methods when binding Xamarin.Android libraries. This tiny little NuGet adds a .targets file to the Xamarin.Android Binding project.

The .targets file adds a MSBuild task which will then read the jar elements and automatically generate the transform files needed to set the parameter names for all the bound methods.

You can view the project source for this on GitHub.

Usage

Using this is very simple, just install the NuGet:

PM> Install-Package Xamarin.Android.Bindings.Generators

Then, rebuild! That is all!

As this is just used for binding projects, it shouldn’t be installed
into Xamarin.Android app projects.

Features

This is currently what is available in the first release:

  • Automatic parsing of InputJar and EmbeddedJar
  • Handles multiple input files
  • Finds available parameter names
  • Missing parameter names are still meaningful (uses type names)
  • Shouldn’t give matched-no-nodes warnings
  • No manual intervention necessary