Nick's .NET Travels

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

Getting Started with Xamarin.Forms and Unit Testing with xUnit and Moq (II)

Previous posts in this sequence on Getting Started with Xamarin.Forms:
Multi-Targeting in Visual Studio, SDK Versions, MvvmCross, Authenticating with ADAL
Refactoring MvvmCross and Services, Effects, Navigation with MvvmCross
Presentation Attributes in MvvmCross, Resources and Styles, Resource Dictionaries
Platform Specific Resources with OnPlatform, Device Customization using OnIdiom
Unit Testing with xUnit and Moq

One of the hardest aspects of testing is implementing and executing platform specific unit tests. As I was putting together a post covering platform specific testing I got side tracked looking at the use of Moq, which I posted about previously. On closer inspection of the csproj of the xUnit test project that I created as part of that post, the target framework is set to netcoreapp2.1. In order to test platform specific features I need to adjust the csproj to be multi-targeted covering android, ios and uwp. By making the test project multi-targeted the code can access platform specific APIs in order to be able to verify the platform specific code in our Core library.

<TargetFrameworks>netcoreapp2.1;Xamarin.iOS10;MonoAndroid90;uap10.0.16299</TargetFrameworks>

If we compare the target frameworks with those used by the Core project of our application, we can see that we have netcoreapp2.1 instead of netstandard2.0. In order to take advantage of the xUnit test runner, the test project does need to target netcoreapp2.1. We don’t really need to add netstandard2.0, since we don’t have a test runner that is only based on netstandard2.0 and our application never actually runs as a .NET Standard application (i.e. it runs as an iOS, Android or UWP application)

After changing the target frameworks the test project doesn’t build for a couple of reasons:

- The Visual Studio xUnit test runner isn’t compatible with the platform specific target frameworks

- xUnit has a platform specific test running that needs to be referenced. I’ll cover the platform specific test runners in future posts

The csproj of the test project should be updated to selectively include package references:

<PropertyGroup>
   <TargetFrameworks>netcoreapp2.1;Xamarin.iOS10;MonoAndroid90;uap10.0.16299</TargetFrameworks>
  <IsNetCoreApp>$(TargetFramework.StartsWith('netcoreapp'))</IsNetCoreApp>
</PropertyGroup>

<ItemGroup Condition=" '$(IsNetCoreApp)' != 'true' ">
   <PackageReference Include="xunit.runner.devices" Version="2.4.48" />
   <PackageReference Include="UnitTests.HeadlessRunner" Version="2.0.0" />
</ItemGroup>

<ItemGroup Condition=" '$(IsNetCoreApp)' == 'true' ">
   <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
   <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0">
   <PrivateAssets>all</PrivateAssets>
   <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
   </PackageReference>
</ItemGroup>

<ItemGroup>
   <PackageReference Include="xunit" Version="2.4.0" />
</ItemGroup>

Even after changing the package references to make them conditional, there were issues referencing the stable release of Moq. Unfortunately the current release of Moq uses some features around reflection that aren’t supported by all platforms, and whilst it’s compatible with netcoreapp2.1, it’s not compatible with netstandard2.0. I went looking for other mocking options and almost immediately came across the work being done on the next iteration of Moq – this is a major change that does more of the heavy lifting at compile time, rather than dynamically at runtime.

At the time of writing, the next release for Moq is currently available only as source code from https://github.com/moq/moq

Once the source code has been built, the assemblies can be added as a direct reference to the test project.

<ItemGroup>
   <Reference Include="Moq">
     <HintPath>..\Library\Moq\Moq.dll</HintPath>
   </Reference>
   <Reference Include="Moq.Sdk">
     <HintPath>..\Library\Moq\Moq.Sdk.dll</HintPath>
   </Reference>
   <Reference Include="Stunts">
     <HintPath>..\Library\Moq\Stunts.dll</HintPath>
   </Reference>
</ItemGroup>

<ItemGroup Condition="'$(DesignTimeBuild)' == 'true'">
   <Analyzer Include="..\Library\Moq\Stunts.dll" />
   <Analyzer Include="..\Library\Moq\Stunts.Sdk.dll" />
   <Analyzer Include="..\Library\Moq\Roslyn.Services.Test.Utilities.dll" />
   <Analyzer Include="..\Library\Moq\Stunts.CodeAnalysis.dll" />
   <Analyzer Include="..\Library\Moq\Stunts.CodeFix.dll" />
   <Analyzer Include="..\Library\Moq\netstandard.dll" />
   <Analyzer Include="..\Library\Moq\Moq.Sdk.dll" />
   <Analyzer Include="..\Library\Moq\Moq.CodeAnalysis.dll" />
   <Analyzer Include="..\Library\Moq\Moq.CodeFix.dll" />
</ItemGroup>

In addition to assembly references, the Moq libraries are also added as Analyzers – this is to allow for the design time generation of code. Which brings me to the next step which is to adjust our test case to make use of the new Moq syntax. Currently the new version of Moq requires the manual inclusion of Mock.cs and Mock.overloads.cs (content files in the output folder that are generated by building the Moq source code) which include a bunch of helper methods that you’ll need.

The basic process for testing with a mock hasn’t changed – you still need to create and setup your mock entities, invoke a series of methods and then verify actual vs expected output:

[Fact]
public async Task AuthenticateTest()
{
     var credentialsMock = Mock.Of<ICredentialService>();
#pragma warning disable CS4014 // Don't await - we're calling Authenticate so that we can train the Mock to return a specific value
     credentialsMock.Authenticate().Returns(()=>Task.FromResult("SomeRandomAccessToken"));
#pragma warning restore CS4014

    var mainViewModel = new MainViewModel(
         null,
         null,
         credentialsMock);
     Assert.True(await mainViewModel.Authenticate());
}

I’ve bolded the lines that are worth reviewing in the amended test method:

- Where previously we created a new instance of Mock<ICredentialService>, now we’re using the method Mock.Of<ICredentialService>.

- Previously we called Setup to define the mocked behaviour. Now, we call the actual method we want to mock and then use the Returns method to define what the behaviour should be. Since we actually want to mock the Task that is returned by the Authenticate method, it’s important that we don’t attempt to await it. Hence the #pragma statements

This code will not currently compile, showing an error stating that there’s currently no mock implementation on ICredentialService. This error is generated by the Moq analysers we added to the csproj.

image

Expanding the help tooltip

image

Following the tooltip suggestion we can go ahead and create the mock for the ICredentialService. This will be added to a “Mocks” folder and appropriately named ICredentialServicesMock.

With that we can go ahead and run the test case.

image

In this post we’ve taken a quick look at getting started with the next version of Moq. We’ll take this further in the next post to cover running platform tests.

Intercepting the Android Software Back Button in Xamarin.Forms

Recently an issue was raised on MvvmCross that claimed there was an issue intercepting the back button in a Xamarin.Forms + MvvmCross application running on Android. I spent a bit of time investigating the issue as I didn’t believe MvvmCross was doing anything that would prevent an application from intercepting the back button. In this post I’ll walk through my investigation and demonstrate a solution that I came up with. Just for clarity, the issue was referring to intercepting the software back button that appears in the navigation bar.

In the comments someone had referenced a solution proposed by Udara Alwis (https://theconfuzedsourcecode.wordpress.com/2017/03/12/lets-override-navigation-bar-back-button-click-in-xamarin-forms/) which states that the OnOptionsItemSelected method can be overridden in the Activity that hosts the Xamarin.Forms application. Further comments indicated that this solution didn’t work for a Xamarin.Forms application that was using MvvmCross. My starting point was to of course validate this assertion. Using the Playground sample in the MvvmCross source code I attempted to override the OnOptionsItemSelected method in the MainActivity of the Android application. I ran the application and sure enough, the OnOptionsItemSelected method does not get invoked when tapping the software back button.

Having validated that the MvvmCross Playground was indeed broken, I next wanted to test to see if it was an issue with Xamarin.Forms itself. To do this, I started by creating a new Xamarin.Forms application (I’m just going to build for Android, since this is just a sample).

image

The Blank application template comes with a single page, MainPage. I added a second page to the application:

image

Onto the MainPage I added a Button and in the Clicked event handler added code to navigate to the page I just added:

private async void Button_Clicked(object sender, EventArgs e)
{
     await Navigation.PushAsync(new Page1());
}

In order to get the navigation bar to appear, I changed the App constructor to make use of a NavigationPage:

public App()
{
     InitializeComponent();

    MainPage = new NavigationPage(new MainPage());
}

Lastly, I needed to add the OnOptionsItemSelected override to the MainActivity.

public override bool OnOptionsItemSelected(IMenuItem item)
{
     return base.OnOptionsItemSelected(item);
}

Unfortunately, after doing all this, the OnOptionsItemSelected method was still not called. Looks like the issue sits with Xamarin.Forms, so it’s time to start trawling through the source code.

After an initial inspection it appears that the FormsAppCompatActivity does override the OnOptionsItemSelected method, but that doesn’t explain why overriding it in my application wouldn’t work. However, further inspection revealed that the NavigationPageRenderer (the renderer for the NavigationPage) implements the IOnClickListener interface and registers itself with the ActionBar (which corresponds to the navigation bar). Doing this prevents the call to the OnOptionsItemSelected method, which is why we were not seeing it called.

I figured that I would try extending the default renderer and provide my own implementation of the IOnClickListener interface:

[assembly: ExportRenderer(typeof(NavigationPage), typeof(HackBackButton.CustomNavigationPageRenderer))]
namespace HackBackButton
{
     public class CustomNavigationPageRenderer : NavigationPageRenderer, IOnClickListener
     {
         public CustomNavigationPageRenderer()
         {
         }

        public CustomNavigationPageRenderer(Context context) : base(context)
         {
         }

        public new void OnClick(Android.Views.View v)
         {
             Element?.PopAsync();
         }
    }
}

This works and the OnClick method is invoked when the software back button is tapped. Of course, we then need to route this to the current page so that it can decide if it should allow the back navigation.

Turns out that it’s nothing to do with MvvmCross and that the issue lie entirely with Xamarin.Forms. There needs to be a better way to intercept the back navigation. Someone has already listed a issue with Xamarin.Forms, so add a comment and make sure this issue gets some attention.

Getting Started with Xamarin.Forms and Unit Testing with xUnit and Moq

Previous posts in this sequence on Getting Started with Xamarin.Forms:
Multi-Targeting in Visual Studio, SDK Versions, MvvmCross, Authenticating with ADAL
Refactoring MvvmCross and Services, Effects, Navigation with MvvmCross
Presentation Attributes in MvvmCross, Resources and Styles, Resource Dictionaries
Platform Specific Resources with OnPlatform, Device Customization using OnIdiom

When we kicked off this project we separated out the business logic from the user interface into Core and UI projects respectively. The main aim was to ensure clear separation of context and to allow for the business logic to be developed, and more importantly, tested, independently of the UI. In this post we’ll get started with unit testing our Core library using xUnit. I’ll also touch on using the mocking library, Moq, to make our testing lives easier.

To get started we’ll add another project to our solution, this time based on the xUnit Test Project (.NET Core) from the Add New Project dialog.

image

If we inspect what gets added we’ll see that it’s a regular single targeted project with references to xUnit and the Microsoft test library.

image

After creating the project, don’t forget to do the obligatory NuGet package update. If you open the UnitTest1 class you can right-click within the Test1 method and select Run Test(s).

image

When you execute tests within Visual Studio you can see the execution progress in the Output window. If it doesn’t automatically switch, you may need to select Tests for the “Show output from” dropdown.

image

Before we can write tests for our Core library, we need to add a reference to the Core library to the Testing library.

image

Now we’re ready to start creating our own tests (you can delete UnitTest1.cs since we won’t be needing it). Everyone has their own naming convention and structure for testing library. I tend to mirror the layout of the project I’m testing. So in this case I've created a ViewModels folder within the test project and have created a class MainViewModelTest class.

At this point I’m also going to add a reference to Moq (https://www.nuget.org/packages/Moq) which I’ll use as part of the test method

public class MainViewModelTest
{
     [Fact]
     public async Task AuthenticateTest()
     {
         var credentialsMock = new Mock<ICredentialService>();
         credentialsMock.Setup(x => x.Authenticate()).Returns(() => Task.FromResult("SomeRandomAccessToken"));

        var mainViewModel = new MainViewModel(
             new Mock<IMvxLogProvider>().Object,
             new Mock<IMvxNavigationService>().Object,
             credentialsMock.Object);
         Assert.True(await mainViewModel.Authenticate());
     }
}

Here I’ve kept the AuthenticateTest method relatively straight forward – I created a mock instance of the ICredentialService which returns a predefined access token; this is then used along with two other mock objects when creating the MainViewModel instance. I then assert that calling the Authenticate returns true (i.e. because the Authenticate method on the ICredentialService instance returns a not-null access token).

Right-click within this test method to run the test returns a positive outcome in the Output window. You can also run and see the results of running test cases via the Test Explorer window.

image

And that’s it, you can now write as many test cases as you feel are necessary for your services, viewmodels and other Core classes.

Getting Started with Xamarin.Forms and Device Customization using OnIdiom

Previous posts in this sequence on Getting Started with Xamarin.Forms:
Multi-Targeting in Visual Studio, SDK Versions, MvvmCross, Authenticating with ADAL
Refactoring MvvmCross and Services, Effects, Navigation with MvvmCross
Presentation Attributes in MvvmCross, Resources and Styles, Resource Dictionaries
Platform Specific Resources with OnPlatform

Last post I covered how to use OnPlatform to tailor resources and styles based on the target platform. However, there is an alternative dimension you can tailor the layout of your application and that’s using OnIdiom. If you look at the definition of the OnIdiom class you can see that it allows you to define different values for Phone, Tablet, Desktop, TV and Watch.

image

To use this in XAML is very similar to using OnPlatform:

<Label>
     <Label.Text>
         <OnIdiom x:TypeArguments="x:String">
             <OnIdiom.Phone>Hello from a phone app</OnIdiom.Phone>
             <OnIdiom.Desktop>Hello from a desktop app</OnIdiom.Desktop>
         </OnIdiom>
     </Label.Text>
</Label>

As you can see from the code snippet this provides different string values for when the application is run on a phone vs being run on a desktop.

Note: Tablet only works well for iOS and Android. Xamarin.Forms running on UWP currently doesn’t distinguish between Windows running in desktop or tablet mode, and as such will always use the Desktop idiom values.

Getting Started with Xamarin.Forms and Platform Specific Resources using OnPlatform

Previous posts in this sequence on Getting Started with Xamarin.Forms:
Multi-Targeting in Visual Studio, SDK Versions, MvvmCross, Authenticating with ADAL
Refactoring MvvmCross and Services, Effects, Navigation with MvvmCross
Presentation Attributes in MvvmCross, Resources and Styles, Resource Dictionaries

In previous posts we’ve looked at using resources and then styles and resource dictionaries in order to manage the style of elements throughout our application. Whilst Xamarin.Forms provides an out-of-the-box cross platform experience, the reality is that if you don’t tweak the layout a bit for each platform, your application is going to look very generic, and not in a good way. In this post we’ll look at some of the different ways that you can adjust layout based on which target platform the application is running on.

The starting point is to look at an individual element, such as a Label, and how an individual property can be adjusted for different platforms using an OnPlatform element.

<Label Text="Hello World!">
     <Label.FontAttributes>
         <OnPlatform x:TypeArguments="FontAttributes">
             <On Platform="Android" Value="Italics"/>
             <On Platform="iOS" Value="None"/>
             <On Platform="UWP" Value="Bold"/>
         </OnPlatform>

     </Label.FontAttributes>
</Label>

In this example instead of supplying a value for the FontAttributes attribute we’ve expanded into long form using a Label.FontAttributes element. Nested within this element we create an OnPlatform element, supplying the TypeArguments attribute to indicate what Type of value the OnPlatform is going to produce. Within the OnPlatform element we then have an On element for each platform we want to specify a value for.

Since we’re not a big fan of having literals specified for an individual element, and even more so when doing per-platform styling, we can also define resources using the OnPlatform syntax:

<OnPlatform x:Key ="FeatureColor" x:TypeArguments="Color">
     <On Platform="Android" Value="Red"/>
     <On Platform="iOS" Value="Green"/>
     <On Platform="UWP"  Value="Blue"/>
</OnPlatform>

This defines a resource, FeatureColor, within a ResourceDictionary, with different colors defined for each of the three platforms.

As you can see, defining values for each platform can start to add a lot of bloat to your XAML. A work around for this is to use a similar technique that we’ve discussed previously where we include files on a per platform basis. For resources this requires a bit of fiddling, so there are a few steps involved. We need to start with the csproj for the UI project and adjust the first ItemsGroup to remove all XAML files that are within the Platforms folder. Next we need to selectively add back the XAML files based on what the target platform is. The bold lines in the following XAML from the csproj file indicate these changes.

<ItemGroup>
   <Compile Remove="Platforms\**\*.cs" />
   <None Include="Platforms\**\*.cs" />
   <EmbeddedResource Remove="Platforms\**\*.xaml" />
   <None Include="Platforms\**\*.xaml" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) ">
   <Compile Include="Platforms\Netstandard\**\*.cs" />
   <EmbeddedResource Include="Platforms\Netstandard\**\*.xaml" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('uap')) ">
   <Compile Include="Platforms\Uap\**\*.cs" />
   <EmbeddedResource Include="Platforms\Uap\**\*.xaml" />
</ItemGroup>

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

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

Next we need to create platform specific XAML files. I simply copied the LiteralResources.xaml and LiteralResources.xaml.cs into each of the Platform folders and renamed both the files and the class name to PlatformLiteralResources. In my case the project structure looks like the following:

image

You’ll notice that the PlatformLiteralResources.xaml is only showing under the Netstandard – this appears to be a bit of a bug in Visual Studio as the file exists and should appear in the project structure for all the platforms. The only thing left to do is define some platform resources and to link the PlatformLiteralResources class into the resource dictionary hierarchy:

PlatformLiteralResources

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="
http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                     xmlns:res="clr-namespace:StrataPark.UI.Resources"
                      x:Class="StrataPark.UI.Resources.PlatformLiteralResources">
     <ResourceDictionary.MergedDictionaries>
         <res:LiteralResources />
     </ResourceDictionary.MergedDictionaries>
    <x:Double x:Key="DefaultLabelFontSize">24</x:Double>
</ResourceDictionary>

StyleAndTemplateResources

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="
http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                     xmlns:res="clr-namespace:StrataPark.UI.Resources"
                     x:Class="StrataPark.UI.Resources.StyleAndTemplateResources">
     <ResourceDictionary.MergedDictionaries>
         <res:PlatformLiteralResources />
     </ResourceDictionary.MergedDictionaries>

    <!-- Other resources -->
</ResourceDictionary>

Note that the hierarchy is now App.xaml >> StylesAndTemplateResources >> PlatformLiteralResources >> LiteralResources.

And there you have it, you can now define platform specific literals in the PlatformLiteralResources xaml file without worrying about using the OnPlatform element.

Getting Started with Xamarin.Forms and Resource Dictionaries

Previous posts in this sequence on Getting Started with Xamarin.Forms:
Multi-Targeting in Visual Studio, SDK Versions, MvvmCross, Authenticating with ADAL
Refactoring MvvmCross and Services, Effects, Navigation with MvvmCross
Presentation Attributes in MvvmCross, Resources and Styles

Last post, on Resources and Styles, we discussed how resources, such as styles, can be defined at different levels within the view hierarchy. In this post we’re going to cover using resource dictionaries to better manage resources. Let’s start by recapping how resources can be defined by starting with a basic application level resource, which are resources that can be accessed anywhere in the application.

<Application.Resources>
     <Thickness x:Key="LeftRightMargin">48,0</Thickness>

As we go down the view hierarchy, we can define resources at a page level, which are resources that will only be accessible to elements on the same page

<Page.Resources>
     <Thickness x:Key="LeftRightMargin">36,0</Thickness>

A couple of things to note here – firstly we’re defining a resource with the same name as at the application level, which means we’re going to be overriding the resource value but only for this page. It’s also worth nothing that we’re using Page.Resources, despite the type of the page being ContentPage (for a normal Xamarin.Forms page) or MvxContentPage (for an MvvmCross page). This is acceptable since Page is the base class for both ContentPage and MvxContentPage, meaning that we can use it to reference the Resources property. It’s up to you whether you use Page.Resources or ContentPage.Resources, or even MvxContentPage.Resources, as they all reference the same property.

We can continue down the hierarchy, defining resources at either the container, or element level. As before, the resources are only accessible to the element and it’s children where the resource is defined.

<Grid.Resources>
     <Thickness x:Key="LeftRightMargin">24,0</Thickness>

<Label.Resources>
     <Thickness x:Key="LeftRightMargin">12,0</Thickness>

Now that we've seen how we can define resources at any level in the view hierarchy but currently we’re storing all our application level resources into the App.xaml, which overtime is going to get quite hard to manage. One approach to make resources easier to manage is to create separate resource dictionaries for different types of resources. My preference is to have a dictionary that contains literals such a colours, strings, Thickness, converters, and another resource dictionary that has styles and templates.

Let’s start by creating a separate dictionary and linking it to our App.xaml. Unfortunately Visual Studio doesn’t currently come with an item template for a ResourceDictionary for Xamarin.Forms. I’m going to create a folder called Resources within the UI project, open the folder in File Explorer and create a new file called StyleAndTemplateResources.xaml.

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="
http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">

    <!-- Add all Style and Template resources here -->
    <Style TargetType="Label"  x:Key="SomeLabelStyle" />
</ResourceDictionary>

This needs to be referenced in App.xaml to ensure the resources are loaded at application startup.

<Application.Resources>
     <ResourceDictionary Source="Resources\StyleAndTemplateResources.xaml"/>
</Application.Resources>

Note that we’re using the new syntax supported in Xamarin.Forms v3+ where we do not need to include the MergedDictionaries tag and we can load the ResourceDictionary based on the path to the XAML. This means that we don’t need to specify the Class attribute in the XAML for the ResourceDictionary; nor do we need the code behind file.

Let’s also add another ResourceDictionary which will contain our literals. This will follow the same structure as the StyleAndTemplateResources.xaml but called LiteralResources.xaml, and we need to update the App.xaml.

<Application.Resources>
    <!-- This will NOT work -->
     <ResourceDictionary Source="Resources\LiteralResources.xaml"/>
     <ResourceDictionary Source="Resources\StyleAndTemplateResources.xaml"/>
</Application.Resources>

As the comment in the XAML states, adding the two resource dictionaries in parallel like this in the App.xaml will not work. At runtime you can expect a XAML parsing error, stating that resources defined in LiteralResources can’t be found when loading resources in StyleAndTemplateResources.

image

This is because both resource dictionaries are loaded independently and then merged into the resource dictionary for the application. In order to reference resources from LiteralResources, it needs to be loaded first, followed by StyleAndTemplateResources. You should be able to do this by chaining resource dictionaries as follows (Warning: this currently does not work!):

App.xaml

<Application.Resources>
    <ResourceDictionary Source="Resources\StyleAndTemplateResources.xaml"/>
< /Application.Resources>

StyleAndTemplateResources

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
     <ResourceDictionary.MergedDictionaries>
         <ResourceDictionary Source="Resources\LiteralResources.xaml"/>
    </ResourceDictionary.MergedDictionaries>

    <!-- Other resources -->
</ResourceDictionary>

So, the question is – if this doesn’t work, what do you have to do? Well the good news is that we’re on the right track using a hierarchy of dictionaries. Unfortunately due to some issues with Xamarin.Forms, we can’t use the simplified form, instead we need to make sure that each resource dictionary has a Class attribute and a code behind file, and we need to explicitly use the MergedDictionaries element.

Start by creating code behind files for both resource dictionaries:

public partial class LiteralResources
{
     public LiteralResources()
     {
         InitializeComponent();
     }
}
public partial class StyleAndTemplateResources
{
     public StyleAndTemplateResources()
     {
         InitializeComponent();
     }
}

Next, we’ll update App.xaml and the other resource xaml files to define the Class attribute and fix the hierarchy:

LiteralResources.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="
http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                      x:Class="StrataPark.UI.Resources.LiteralResources">
     <Thickness x:Key="LeftRightMargin">48,0</Thickness>

    <x:Double x:Key="DefaultLabelFontSize">24</x:Double>
     <Color x:Key="FeatureColor">Green</Color>
</ResourceDictionary>

StyleAndTemplateResources.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="
http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                     xmlns:res="clr-namespace:StrataPark.UI.Resources"
                     x:Class="StrataPark.UI.Resources.StyleAndTemplateResources">
     <ResourceDictionary.MergedDictionaries>
         <res:LiteralResources />
     </ResourceDictionary.MergedDictionaries>

    <Style x:Key="FeatureLabelStyle" TargetType="Label">
         <Setter Property="TextColor" Value="{StaticResource FeatureColor}"/>
         <Setter Property="FontSize" Value="{StaticResource DefaultLabelFontSize}"/>
     </Style>

    <Style TargetType="Label" BasedOn="{StaticResource FeatureLabelStyle}"/>
</ResourceDictionary>

App.xaml

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="
http://xamarin.com/schemas/2014/forms"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              xmlns:res="clr-namespace:StrataPark.UI.Resources"
              x:Class="StrataPark.UI.App">
     <Application.Resources>
         <ResourceDictionary>
             <ResourceDictionary.MergedDictionaries>
                 <res:StyleAndTemplateResources />
             </ResourceDictionary.MergedDictionaries>
         </ResourceDictionary>
    </Application.Resources>
</Application>

And there you have it – resources are separated out for easier maintainability.

Getting Started with Xamarin.Forms with Resources and Styles

Previous posts in this sequence on Getting Started with Xamarin.Forms:
Multi-Targeting in Visual Studio, SDK Versions, MvvmCross, Authenticating with ADAL
Refactoring MvvmCross and Services, Effects, Navigation with MvvmCross
Presentation Attributes in MvvmCross

In this post we’re going to look at how you can adjust the default style for the controls that you use within your Xamarin.Forms application. To get started, let’s look at how you might change the colour of a basic Label – there are a couple of options but all start with setting the TextColor property:

<Label TextColor="#0F0" />
<Label TextColor="#00FF00" />
<Label TextColor="Green" />

A lot of applications will have all sorts of layout properties set explicitly in the page XAML. Unfortunately this becomes increasingly hard to manage as the application grows. Imagine having 10+ pages all with the colour of elements set explicitly and then you want to change the theme of the application – this would require going through every element to make sure every colour is correct.

An alternative is to extract various properties into static resources where they can be managed at an application, page or even control level. Let’s look at defining an application resource in the App.xaml file in the UI project.

<Application xmlns="http://xamarin.com/schemas/2014/forms"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              x:Class="StrataPark.UI.App">
     <Application.Resources>
         <Color x:Key="FeatureColor">Green</Color>
    </Application.Resources>
</Application>

In this case we’ve defined a Color resource with a Key of FeatureColor. This can be used anywhere in the application using the Key.

<Label TextColor="{StaticResource FeatureColor}" />

Extract properties into resources can be done for all sorts of values such as strings, colours, margins etc. Not all resources need to be defined at an application level. Resources can be added to the Resources dictionary of a Page or even a control (for example a Grid) – this limits the scope of that resource to the element where the resource is defined, and it’s children. For example, adding a resource to the Resources dictionary of a Page means that the resource is available to all elements on that page but not to elements on other pages within the application.

Note: It may seem simpler to add all resources to the Application Resources dictionary – just be aware that there is a performance cost associated with this as all resources will need to be loaded when the application is started up. Depending on the number and complexity of the resources, this can have a negative impact on the startup time for your application.

Returning to the example of setting the colour of the text of a Label, creating the FeatureColor resource makes it easy to apply the same colour to a number of Label elements and then to be able to change their colour in one place. However, there are two issues here:

- What if we want to be able to set other common properties across all these Label elements? For example, we might want to set FontSize.

- We still have to explicitly set the TextColor on each Label – it would be great if the colour could be set automatically on all Label elements.

The answer to both of these is to define a Style, which you can think of as a collection of property setters, applied by setting the Style property of an element. Let’s start with the first issue where we want to be able to set the FontSize as well as the colour. To do this we’ll create a Style called FeatureLabelStyle, again in the App.xaml so it can be used throughout the application.

<x:Double x:Key="DefaultLabelFontSize">24</x:Double>
<Color x:Key="FeatureColor">Green</Color>

<Style x:Key="FeatureLabelStyle" TargetType="Label">
     <Setter Property="TextColor" Value="{StaticResource FeatureColor}"/>
     <Setter Property="FontSize" Value="{StaticResource DefaultLabelFontSize}"/>
</Style>

Note that we still have a resource called FeatureColor which specifies the colour of the Label, and we have another resource that defines the size to be used for the FontSize. These are combined into the FeatureLabelStyle, which can then be applied by setting the Style property.

<Label Style="{StaticResource FeatureLabelStyle}" />

Moving now to the second issue, which is how we can apply a Style to all Label elements. Currently the Style we have defined has a Key assigned to it, making it an explicit Style, since the Key has to be used in order to explicitly specify the Style. In order to apply it to all elements we need to define an implicit style, a Style with no Key.

<Style TargetType="Label" BasedOn="{StaticResource FeatureLabelStyle}"/>

The implicit Style will be automatically applied by default to all Label elements. Note that we have based the implicit Style on the previously defined explicit style – this is best practice as it means we can take advantage of Style inheritance. For example you might have a base explicit Style that defined the default colour for all Label styles.

And there you have it, a quick overview of using Resources and Styles within your Xamarin.Forms application.

Getting Started with Xamarin.Forms and Presentation Attributes in MvvmCross

Previous posts in this sequence on Getting Started with Xamarin.Forms:
Multi-Targeting in Visual Studio, SDK Versions, MvvmCross, Authenticating with ADAL
Refactoring MvvmCross and Services, Effects, Navigation with MvvmCross

The great thing about MvvmCross is that it provides a minimal effort approach to things like navigation. However, there are times when you want to override the navigation model. For example you might want a page to appear as a modal page instead of a regular page. MvvmCross allows you to do this by overriding the default way that a page is presented, which is controlled by a presentation attribute applied to the page. Out of the box, MvvmCross comes with a number of presentation attributes that you can use to control how a page is rendered. By default, if you attempt to navigate to a page, MvvmCross assumes that you just want to navigate to that page using the Xamarin.Forms PushAsync method. This is the same as if you had attributed the page with the MvxContentPagePresentation attribute e.g.

[MvxContentPagePresentation]
public partial class MainPage

Note: By default you do not need to attribute each page with an attribute if you just want to navigate to the page. You can use the MvxContentPagePresentation attribute to override the back stack (i.e. using a combination of the NoHistory and WrapInNavigation properties)

I’m going to change the ProfilePage to appear as a modal page. The only change I need to make is to add the MvxModalPresentation attribute to the ProfilePage class.

[MvxModalPresentation]
public partial class ProfilePage

Now when I run the application the Profile Page will appear as a modal page. Unfortunately there is currently no way to dismiss the modal page, so the application will get stuck with the ProfilePage displayed. To fix this, let’s add a button to the ProfilePage that will be used to close the modal page. Again, I’ll start by showing how to close the page in code behind using the Xamarin.Forms navigation construct:

<Button Text="Close" Clicked="CloseClicked"/>

private async void CloseClicked(object sender, System.EventArgs e)
{
    await Navigation.PopModalAsync();
}

Note: Xamarin.Forms distinguishes between closing a modal page using PopModalAsync vs closing a regular page using PopAsync.

Of course, we’d prefer to have the button linked to a command in the view model that can be used to close the corresponding page. The code for the Button and the ProfileViewModel are as follows.

<Button Text="Close" Command="{Binding CloseCommand}"/>


public class ProfileViewModel: MvxNavigationViewModel
{
     private IMvxCommand closeCommand;

    public ProfileViewModel(IMvxLogProvider logProvider, IMvxNavigationService navigationService) : base(logProvider, navigationService)
     {
     }

    public IMvxCommand CloseCommand => closeCommand ?? (closeCommand = new MvxAsyncCommand(()=>NavigationService.Close(this)));
}

Note: The ProfileViewModel inherits from the MvxNavigationViewModel so that it can access the NavigationService.

The NavigationService exposes a Close method which will close the current view model, and the corresponding page. This code is the same irrespective of whether the ProfilePage is shown as a regular or a modal page.

There you have it – you can easily override how pages are displayed in your Xamarin.Forms application using presentation attributes in MvvmCross. There are other attributes that come with MvvmCross to allow you easily display pages in master-detail, tabbed and carousel layouts.

image

In addition to the built in attributes, you can override the MvxPagePresentation attribute and add your own custom layout logic for how pages are presented.

Getting Started with Xamarin.Forms and Navigation with MvvmCross

Previous posts in this sequence:
Getting Started with Xamarin.Forms and Multi-Targeting in Visual Studio
Getting Started with Xamarin.Forms and SDK Versions
Getting Started with Xamarin.Forms with MvvmCross
Getting Started with Xamarin.Forms and Authenticating with ADAL
Getting Started with Xamarin.Forms, Refactoring MvvmCross and Services
Getting Started with Xamarin.Forms and Effects

Xamarin.Forms has a built in mechanism for navigating between pages. Let’s start with navigating from the MainPage to a new ProfilePage, based on the Content Page item template, added to the Pages folder of the UI project.

image

To trigger the navigation, we’ll add a new Button to the MainPage and add logic to navigate to the ProfilePage.

<Button Text="Profile" Clicked="ProfileClicked"/>

private async void ProfileClicked(object sender, System.EventArgs e)
{
     await Navigation.PushAsync(new ProfilePage());
}

Navigation between pages includes adding a back button and handles any hardware back button

imageimage

The limitation with the built in navigation model for Xamarin.Forms is that it is triggered in the UI layer (i.e. in the code behind of the MainPage). Using MvvmCross we can move the navigation logic into the domain of the view model, meaning it can be tested independently of the UI.

To do this, we need to add a ProfileViewModel class, which corresponds to the ProfilePage.

image

The ProfileViewModel should inherit from MvxViewModel:

public class ProfileViewModel: MvxViewModel
{
}

The ProfilePage also needs to be updated to inherit from MvxContentPage.

We can now update the MainViewModel to expose a command that can be used to navigate to the ProfileViewModel:

private IMvxCommand profileCommand;
public IMvxCommand ProfileCommand => profileCommand ?? (profileCommand = new MvxAsyncCommand(ShowProfile));
private async Task ShowProfile()
{
     var navService = Mvx.IoCProvider.Resolve<IMvxNavigationService>();
     await navService.Navigate<ProfileViewModel>();

}

The code in the MainPage can now be changed to connect the button to the ProfileCommand in MainViewModel.

<Button Text="Profile" Command="{Binding ProfileCommand}"/>

Navigation is now triggered from the ProfileViewModel.

Refactoring to use MvxNavigationViewModel

The code added to the ShowProfile method uses the Mvx IoC container to look up the IMvxNavigationService. This isn’t great as it is a hidden dependency. An alternative would be to add the IMvxNavigationService as a parameter to the MainPage constructor, which would be injected automatically

public MainViewModel(IMvxNavigationService navigationService, ICredentialService credentialService)

Adding the IMvxNavigationService as a parameter in the constructor means that the view model has to maintain a reference to it until it’s used by the ShowProfile method. Alternatively, we can change the base class to use the MvxNavigationViewModel which already exposes a NavigationService property.

public MainViewModel(IMvxLogProvider logProvider, IMvxNavigationService navigationService, ICredentialService credentialService) : base(logProvider, navigationService)

and the updated ShowProfile method is:

private async Task ShowProfile()
{
     await NavigationService.Navigate<ProfileViewModel>();
}

Navigation using MvvmCross provides a nice abstraction away from the UI layer. It can also be customised to display master-detail, tabbed and other page types.

Getting Started with Xamarin.Forms and Effects

Previous posts in this sequence:
Getting Started with Xamarin.Forms and Multi-Targeting in Visual Studio
Getting Started with Xamarin.Forms and SDK Versions
Getting Started with Xamarin.Forms with MvvmCross
Getting Started with Xamarin.Forms and Authenticating with ADAL
Getting Started with Xamarin.Forms, Refactoring MvvmCross and Services

At some point in building a cross platform application using Xamarin.Forms you’ll need to build out some platform specific features. There are a couple of ways to do this, depending on what you want to achieve. One of those ways is to use an Effect. In this example we’re going to create an Effect that can be used to add a tooltip to any element. For the purposes of this exercise we’re going to assume that this only makes sense to add on UWP where the application can be used on a desktop where the user has a mouse and keyboard attached.

An Effect has two parts:

- A platform agnostic class which will contain any properties that the Effect needs to expose in XAML. This is the name of the element that will appear in XAML. In this case the class will be called TooltipEffect and inherits from RoutingEffect

- A platform specific class which provides the platform specific implementation. In this case this class will be called TooltipPlatformEffect and inherits from PlatformEffect. Note that as this is platform specific, it needs to reside in the platform specific folder

As an Effect is a UI component, it should be added to the UI project, which should now look something like:

image

A couple of things to note here:

- There are folders for Converters, Effects and Renderers – I’ve added these as they are common elements that you’ll be adding to your UI project

- I’ve moved MainPage into a folder called Pages

- In a lot of cases I’ll have another folder called Controls, which will contain any custom or user controls I build.

- The TooltipEffect class sits in the Effects folder (platform agnostic)

- The TooltipEffect.Platform file, which contains the TooltipPlatformEffect class, sits in the Uap platform specific folder

Now, let’s look at the implementation of the effect. First, we’ll start with the TooltipEffect:

public class TooltipEffect : RoutingEffect
{
     public TooltipEffect() : base("StrataPark.TooltipEffect")
     {
     }

    public string Tooltip { get; set; }
}

This class exposes a Tooltip string property which will be used to specify the tooltip text in XAML. In the call to the base constructor it passes in a unique identifier for the Effect. This is important to note because it needs to align with the identifier used by the platform specific implementation. Speaking of which, here’s the TooltipPlatformEffect:

[assembly: ResolutionGroupName("StrataPark")]
[assembly: ExportEffect(typeof(TooltipPlatformEffect), nameof(TooltipEffect))]

namespace StrataPark.UI.Effects
{
     [Preserve]
     public class TooltipPlatformEffect : PlatformEffect
     {
         protected override void OnAttached()
         {
             var view = Control ?? Container;

            var effect = Element.Effects.OfType<TooltipEffect>().FirstOrDefault();
             if (!string.IsNullOrWhiteSpace(effect?.Tooltip) && view != null)
             {
                 var toolTip = new ToolTip
                 {
                     Content = effect?.Tooltip
                 };
                 ToolTipService.SetToolTip(view, toolTip);
             }
         }

        protected override void OnDetached()
         {
         }
     }
}

The most important part of this code are the assembly level attributes that register both the namespace (i.e. the StrataPark prefix) and the element identifier (nameof(TooltipEffect) gives the second part of the identifier, “ToolTipEffect”). If the combination of these attributes don’t yield the same identifier set in the platform agnostic Effect, the platform specific implementation won’t be loaded at runtime.

You can now use this Effect in XAML as follows

<Button Text="Authenticate" Command="{Binding AuthenticateCommand}">
     <Button.Effects>
         <effects:TooltipEffect Tooltip="Welcome tooltip"/>
    </Button.Effects>
</Button>

One last note – when adding folders to your project, you should keep an eye on the changes that take place in your csproj. When you add/remove files and folders, occasionally Visual Studio will add unnecessary items to the csproj. Remember that by default files and folders will be include in the new csproj format. So for example, the following xml is not required, and should be removed, prior to checking your code in:

<ItemGroup>
   <Folder Include="Converters\" />
   <Folder Include="Renderers\" />
</ItemGroup>

As you’ve seen, Effects are one way to add platform specific UI logic to your application. An alternative, is to use Renderers but that’s a topic for another post.

Debugging Not Working for .NET Standard library in UWP Application

I was attempting to debug some code in a .NET Standard library that was being referenced from a Xamarin.Forms base UWP application. Unfortunately, it didn’t matter where I set the breakpoint in the library, they were never hit. Initially I thought that this was related to it being a multi-targeted project but it turns out this same issue applies to a regular .NET Standard library.

The only hint I had was when the application was running there was a yellow warning triangle on my breakpoint which a pretty unhelpful, yet accurate, message.

image

Now you’d have thought that since this project was included in the same solution as the application, that it was being built by Visual Studio as part of building and running the application, that you wouldn’t have to do anything special to get step through debugging to work. This is not the case – it appears that debug symbols can’t be loaded – huh! I mean seriously, we expect better.

I had also recently installed the first preview of Visual Studio 2017 15.9 so I thought that might be the issue but no, even opening it in 15.8 still showed the same issue.

So it turns out that there is an issue with the default build configuration – open project properties for the .NET Standard library and click on Advanced under the Build tab

image

The default “Debugging information” value of Portable is what the issue is. Change this to Full or Pdb-only

image

Doing this will set the debugging settings for the currently selected target framework and platform. For example for my project it generated:

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netstandard2.0|AnyCPU'">
   <DebugType>pdbonly</DebugType>
   <DebugSymbols>true</DebugSymbols>
</PropertyGroup>

I simplified this so that it would always use these debugging settings when doing a Debug build

<PropertyGroup Condition="'$(Configuration)'=='Debug'">
   <DebugType>pdbonly</DebugType>
   <DebugSymbols>true</DebugSymbols>
</PropertyGroup>

And there you have it – step through debugging should now work. I’m not sure why it’s so hard for Visual Studio to either use this option by default, or at least provide a useful warning that directs the developer to either documentation, or actually switches the setting automatically.

Getting Started with Xamarin.Forms, Refactoring MvvmCross and Services

Previous posts in this sequence:
Getting Started with Xamarin.Forms and Multi-Targeting in Visual Studio
Getting Started with Xamarin.Forms and SDK Versions
Getting Started with Xamarin.Forms with MvvmCross
Getting Started with Xamarin.Forms and Authenticating with ADAL

In this post I’m going to do a bit of a refactor based on the work completed in the previous post where we added code directly into the MainViewModel to use the Azure Active Directory Authentication Library. This would be fine if the MainViewModel was the only view model in the application that needed access to the Authenticate method. As I will probably want to make use of it elsewhere, I’ve decided to refactor that code into a class called CredentialService.

When I wired up MvvmCross a couple of posts ago, I did so without going into much detail on how the relationship between view models and their corresponding page is setup. I’m not going to delve into the inner workings of MvvmCross but suffice to say that there is some reflection magic that goes on based on the names of the classes. A view model with the name MainViewModel will be paired with a page called MainPage.

In addition to the magic that glues the view model and pages together (and thus the navigation model) MvvmCross also has a quite powerful dependency injection framework. The CredentialService that I’ll be creating will be registered with the DI framework as a singleton that can be easily accessed.

Let’s start by creating the CredentialService and it’s corresponding interface ICredentialService in a folder called Services in the Core library.

public partial class CredentialService:ICredentialService
{
     private const string AuthEndpoint = "
https://login.microsoftonline.com/{0}/oauth2/token";

    private const string ResourceId = "https://graph.windows.net/";
     private const string TenantId = "[your tenantId]";
     private const string ClientId = "[your clientId]";
     private const string RedirectURI = "[your redirectURI]";

    public string AccessToken { get; set; }

    public async Task<string> Authenticate()
     {
         string authority = string.Format(CultureInfo.InvariantCulture, AuthEndpoint, TenantId);
         var authContext = new AuthenticationContext(authority);

        var result = await authContext.AcquireTokenAsync(ResourceId, ClientId, new Uri(RedirectURI), this.PlatformParameters);
         AccessToken = result.AccessToken;
         return AccessToken;
     }
}

public interface ICredentialService
{
     Task<string> Authenticate();
}

The platform specific code will need to be extracted out of the MainViewModel.Platform.cs into the corresponding CredentialService.Platform.cs. For example the UWP class would be:

public partial class CredentialService
{
     private IPlatformParameters PlatformParameters => new PlatformParameters(PromptBehavior.Always, false);
}

In order to register the CredentialService with the DI framework, we just need to add a small bit of code to the Initialize method of the App class in the Core library

public override void Initialize()
{
     CreatableTypes()
         .EndingWith("Service")
         .AsInterfaces()
         .RegisterAsLazySingleton();

    RegisterAppStart<MainViewModel>();
}

The last step is to make use of the service in the MainViewModel. We do this by adding a parameter of type ICredentialService to the MainViewModel constructor.

private ICredentialService CredentialService { get; }
public MainViewModel(ICredentialService credentialService)
{
     CredentialService = credentialService;
}

private async Task Authenticate()
{
     Debug.WriteLine(await CredentialService.Authenticate());
}

And that’s it – we haven’t changed any functionality but the solution is better organised and structured in a way that services can easily be added without cluttering up view models.

image

Getting Started with Xamarin.Forms and Authenticating with ADAL

Previous posts in this sequence:
Getting Started with Xamarin.Forms and Multi-Targeting in Visual Studio
Getting Started with Xamarin.Forms and SDK Versions
Getting Started with Xamarin.Forms with MvvmCross

Now that we’ve got the basics of an application, we’re going to add some authentication using the Azure Active Directory Authentication Library. We’re going to start with registering an application with Azure Active Directory (AAD) (the docs do cover this here but I figured I’d cover it again anyway). Start by heading over to the Azure portal and selecting Azure Active Directory from the set of tabs on the left.

image

In the list of tabs for the AAD, find the App Registrations tab

image

Click “New application registration” and fill in the details for the new app

image

Note that the Sign-on URL doesn’t have to be a real URL, just one that both the portal and the app know about – we’ll use this later! After you’re done creating the app registration you should be able to retrieve the Application ID. Save this information for later as we’ll need it when we’re authenticating the user within our application.

image

The pieces of information you’ll need in order to use ADAL within your application are:

clientId – This is the Application ID that was displayed after you created the app registration in the Azure portal. This is a GUID

redirectUri – This is the Redirect URI that you specified when creating the app registration. If you didn’t write this down, or you want to double check, or change it, you can do so by clicking the Redirect URIs tab under Settings for the app registration. This is a URL (e.g. https://stratapark)

resourceId – This is the identifier of the resource you want to access. In this case we just want to authenticate the user, so we’re going to use the default resource, which is the AAD directory itself, https://graph.windows.net/. This can be a URL or a GUID depending on the type of resource you’re referencing

tenantId – This is the identifier of the tenant that you’re authenticating against. This can be the URL or GUID of your tenant.

To retrieve the tenantId you need to select the Properties tab of the Azure Active Directory and copy the Directory ID

imagehttps://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory/

Now that we’ve setup the app registration, we’re good to start writing some code. Firstly, we need to add a reference to the ADAL library from NuGet – search for Microsoft.IdentityModel.Clients.ActiveDirectory

image

Add the ADAL library to all projects.

Let’s start with the UI and add a button to the MainPage.

<Button Text="Authenticate" Command="{Binding AuthenticateCommand}" />

And of course we need a command within the MainViewModel. In fact we’ll add the bulk of the authentication code to the MainViewModel too:

private IMvxCommand authenticateCommand;
public IMvxCommand AuthenticateCommand => authenticateCommand ?? (authenticateCommand = new MvxAsyncCommand(Authenticate));

private const string AuthEndpoint = "https://login.microsoftonline.com/{0}/oauth2/token";

private const string ResourceId= "https://graph.windows.net/";
private const string TenantId = "[your tenantId]";
private const string ClientId = "[your clientId]";
private const string RedirectURI = "[your redirectUri]”;

public async Task Authenticate()
{
     string authority = string.Format(CultureInfo.InvariantCulture, AuthEndpoint, TenantId);
     var authContext = new AuthenticationContext(authority);

    var result = await authContext.AcquireTokenAsync(ResourceId, ClientId, new Uri(RedirectURI), PlatformParameters);
     Debug.WriteLine( result.AccessToken);
}

The only thing missing is the PlatformParameters (bolded in the code above). As the name suggests, these are platform specific parameters required by the ADAL library. For each platform we need to expose a property that returns an IPlatformParameters within the MainViewModel.Platform.cs for each platform.

Android

private IPlatformParameters PlatformParameters => new PlatformParameters(CurrentActivity, true, PromptBehavior.Auto);
public Activity CurrentActivity
{
     get
     {
         var top = Mvx.IoCProvider.Resolve<IMvxAndroidCurrentTopActivity>();
         return top.Activity;
     }
}

iOS

private IPlatformParameters PlatformParameters => new PlatformParameters(GetTopViewController(),true, PromptBehavior.Auto);
public static UIViewController GetTopViewController()
{
     var window = UIApplication.SharedApplication.KeyWindow;
     var vc = window.RootViewController;
     while (vc.PresentedViewController != null)
         vc = vc.PresentedViewController;

    if (vc is UINavigationController navController)
         vc = navController.ViewControllers.Last();

    return vc;
}

UAP

private IPlatformParameters PlatformParameters => new PlatformParameters(PromptBehavior.Always, false);

NetStandard

private IPlatformParameters PlatformParameters => null;

Note: you need to provide the NetStandard implementation otherwise the NetStandard target won’t build.

There is one more thing we need to add. Android requires an additional piece of code within the Activity that hosts the Xamarin.Forms application

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
     base.OnActivityResult(requestCode, resultCode, data);
     AuthenticationAgentContinuationHelper.SetAuthenticationAgentContinuationEventArgs(requestCode, resultCode, data);
}

If your Android application authenticates but doesn’t ever return the access token, chances are that your OnActivityResult override is either missing, or on the wrong Activity – I spent a bit of time trying to work out why iOS and UWP worked but Android would just hang; turns out I was missing this override.

There you have it – you’re good to go with using ADAL to authenticate your users within your Xamarin.Forms application

Getting Started with Xamarin.Forms with MvvmCross

Previous posts in this sequence:

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

Getting Started with Xamarin.Forms and SDK Versions

Next up is adding in MvvmCross – no surprises here: Add the MvvmCross package to all projects in the solution

image

We need to make a few adjustments to the Core library. First up, we need to add an App class to Core that inherits from MvxApplication. For the moment the only thing this class is going to do is to set the initial view model of the application. One of the core ideas behind MvvmCross is that navigation is driven from view models, rather than at the view level. By setting the initial view model, we’re effectively defining which view will be shown when our application launches.

public class App : MvxApplication
{
     public override void Initialize()
     {
         RegisterAppStart<MainViewModel>();
     }
}

We’ll do a bit of tidying up whilst we’re making changes to the Core project. We’ll create a ViewModels folder and move MainViewModel into folder

We’ll update MainViewModel and MainViewModel.Platform.cs (all four) to add ViewModels to namespace. We’ll also update MainViewModel to inherit from MvxViewModel.


Now that we’ve updated the Core library, we’ll turn our attention to the UI library and the head projects. We’ll add the MvvmCross.Forms NuGet reference to all projects, except Core.

image

The only other change we need to make to the UI library for the moment is to update MainPage to inherit from MvxContentPage instead of ContentPage. You’ll need to do this in both the xaml and xaml.cs files. However, I would recommend dropping the inheritance from the xaml.cs file as it is not required in multiple places.


Next up we need to adjust each of the head projects (UWP, iOS and Android) so that they use MvvmCross to launch the Xamarin.Forms views.

UWP

Rename MainPage to HostPage (in both MainPage.xaml and MainPage.xaml.cs, and the filenames themselves) in the UWP head project – we do this to avoid any confusion between the name of the page and any views that are automatically associated with MainViewModel. Also update HostPage to inherit from MvxFormsWindowsPage.

For UWP we need an additional step due to some limitation around the support for generics. Add a help class ProxyMvxApplication, defined as follows:

public abstract class ProxyMvxApplication : MvxWindowsApplication<MvxFormsWindowsSetup<Core.App, UI.App>, Core.App, UI.App> { }

Change App.xaml and App.xaml.cs to inherit from ProxyMvxApplication, and remove all code in App.xaml.cs other than the constructor which should contain a single call to InitializeComponent. Override the HostWindowsPageType method in the App class

protected override Type HostWindowsPageType()
{
     return typeof(HostPage);
}

Build and run the UWP application

iOS

Update the AppDelegate as follows

public partial class AppDelegate : MvxFormsApplicationDelegate<MvxFormsIosSetup<Core.App, UI.App>, Core.App, UI.App>
{ }

Build and run the iOS application.

Android

Rename and update the MainActivity as follows. Again, we rename the activity to avoid confusion with any activity or view that would be automatically associated with MainViewModel.

public class HostActivity
         : MvxFormsAppCompatActivity<MvxFormsAndroidSetup<Core.App, UI.App>, Core.App, UI.App>
{ }

Build and run the Android application.

You may experience a build error when you attempt to build and run the Android application, relating to referencing the Mono.Android.Export library. In this case, use the Add Reference dialog to manually add the missing reference.

image


There you have it – all three platforms running Xamarin.Forms application powered by MvvmCross.

Getting Started with Xamarin.Forms and SDK Versions

In my previous post I did a walk through of creating a new Xamarin.Forms application and setting up the Core and UI projects for multi-targeting. Whilst I covered updating the various NuGet packages, I didn’t look at the SDK versions for the three platforms. In this post I’m going to look at the options for setting the SDK version, as it’s important that you update this to target the latest SDK version, even if your application is going to support older platform versions.

Android

If you right-click on the Android head project and select Properties you’ll see the Project Properties pane.

Start by increasing the Target Framework by selecting the highest Android version that you have installed

image

Next, on the Android Manifest tab, select “Use Compile using SDK version” under the Target Android version. On this tab you can also set the Minimum Android version if you don’t want to accept the defaults – this may be relevant if you don’t want a massive support matrix for your application as it will prevent installation on devices running a version of Android older than the minimum.

image

Build and run the Android application to make sure you haven’t broken anything and then commit your changes – in this case the first change would have made changes to the Android csproj file, whereas the second change would have changed the AndroidManifest.xml file.

iOS

Setting the SDK Version for iOS is straight forward and the recommendation is to leave the “Default” (which should be the default value) in the SDK Version dropdown on the iOS Build tab on the Properties pane for the iOS application.

image

If you want to adjust the minimum supported version of iOS, you can do this by double-clicking the Info.plist file for your iOS application and then adjusting the Deployment Target.

image


UWP

Both the Target and Min version of the UWP application can be set from the Application tab of the Project Properties pane. Setting the Target version defines the SDK version that will be used to compile the application and thus the APIs that are available.

image


Core and UI

Now that the Core and UI libraries are set to be multi-targeted it is also necessary to define what the target framework/version should be for each platform. If you don’t do this, you may be limited as to what platform APIs are available. Rather than setting these values in each of the libraries, we can create a file, Directory.build.targets, in the solution folder and include the appropriate elements there – this will get included in all projects that support the new csproj format. In this case the contents of our Directory.build.targets file will look like

<Project>
   <PropertyGroup Condition="$(TargetFramework.StartsWith('netstandard'))">
     <DefineConstants>$(DefineConstants);NETSTANDARD;PORTABLE</DefineConstants>
   </PropertyGroup>
   <PropertyGroup Condition="$(TargetFramework.StartsWith('uap'))">
     <DefineConstants>$(DefineConstants);NETFX_CORE;XAML;WINDOWS;WINDOWS_UWP</DefineConstants>
     <TargetPlatformVersion>10.0.17134.0</TargetPlatformVersion>
     <TargetPlatformMinVersion>10.0.16299.0</TargetPlatformMinVersion>
   </PropertyGroup>
   <PropertyGroup Condition="$(TargetFramework.StartsWith('Xamarin.iOS'))">
     <DefineConstants>$(DefineConstants);MONO;UIKIT;COCOA;IOS</DefineConstants>
   </PropertyGroup>
   <PropertyGroup Condition="$(TargetFramework.StartsWith('MonoAndroid'))">
     <DefineConstants>$(DefineConstants);MONO;ANDROID</DefineConstants>
   </PropertyGroup>
</Project>

The csproj for both Core and UI projects also needs to be updated to replace the target framework MonoAndroid81 with MonoAndroid90.

All your projects should now be targeting the latest framework/sdk versions. If you find that some, or all, of these changes don’t take effect, you may need to either reload specific projects, or restart Visual Studio.

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.

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

MVX=0F Side Note: Adding a Splash Screen

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

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

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

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

Declarative C# as an alternative to XAML

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

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

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

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

Xamarin Forms gets CSS to pander to web developers

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

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

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

- CSS is less verbose

- CSS offers additional styling inheritance

-  CSS can be shared between web and Xamarin Forms applications

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

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

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

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

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

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

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

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