Nick's .NET Travels

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

What’s a Progressive Web Applications (PWA) and Why does my website want to be one?

My last couple of posts (App or not to App and Cross-platform applications – PhoneGap/Cordova, Xamarin, PWAs and now Flutter) have been discussing different aspects of build applications. In particular in my previous post I discussed deployment models as being one dimension of applications. In this post I’m going to focus a bit more on the one of the hottest topics going around at the moment, Progressive Web Applications, or just PWA for short. If you’re new to this topic, I’d suggest a quick detour across to the Google developer site where they have an entire section dedicated to PWAs, and it’s a great starting point to understand the importance of PWAs and the experience that a good PWA should deliver.

Side note: I had to laugh when I first went to the PWA page on the Google developer site as it talks about “A new way to deliver amazing user experiences on the web”. This is really what happens when you let the marketing get out in front of technology. Unfortunately I’ve see this type of propaganda so many times (Flash, Silverlight, HTML5) that it actually makes me a bit nervous as I start to think about another learning curve.

image

One of the quickest ways to get past the marketing fluff is to click the PWA Checklist button in the top right corner of the PWA page. Here’s a list of some of the other useful links on the Google developer site in relation to PWAs:

- PWA Checklist

- Lighthouse

- PWA Summit videos (a bit dated but still a good place for building familiarity)

Now that I’ve assigned you a bit of reading, let’s talk about what all the fuss is about. After scanning through the PWA checklist it becomes very evident that there are a couple of key topics: security, offline, seo and notifications. Let’s break these down, with specific attention to why they’re all important aspects of a great application (not just a PWA).

Security

Whilst not the first topic that comes up in regards to PWAs in the checklist it’s very evident that security first is still a key mantra when building the next generation of applications, which is made clear by the first item in the checklist which indicates that all content should be delivered across HTTPS.

In the context of application development there has been an increase flow towards the use of HTTPS (for example the release notes for iOS9 by Apple indicated that all new apps should use HTTPS). Without HTTPS it’s just too easy for any third party to intercept and read/modify the traffic to and from the application.

Offline

This is a biggie when it comes to PWAs and in fact you could argue that this is probably the most significant departure from traditional web development. The introduction of service workers that can intercept requests, cache and dynamical change request behaviour opens the world to building intelligent offline-enabled applications. However, from an offline-ready application development perspective the current thinking in this space seems relatively immature, with most of the priority being placed on caching the components that make up the application (ie the HTML, CSS, JS that make up the application), rather than offline data and synchronisation scenarios.

SEO

Optimising your application for search has been one of those things that every developer says they’re going to do but rarely do they do it, and seldom is it done well. In terms of application development, one of the challenges faced by developers is how to define a set of deep links that will resolve both on the web and in the app. In structuring an application, it should be possible to provide an external link to any part of the applications, and in an ideal world the the link can be shared via any method, whether it be a link on social media, or via private correspondence such as chat or email. The upshot is that by structuring an application this way, you’re already half way there to making it indexable – you just need to make sure that the web application can be statically crawled so that relevant sections will appear in search results.

Notifications

Another aspect that tends to differentiate a good application is one where the user doesn’t have to keep on opening the application in order to see whether anything important has happened. All the native platforms, Windows, iOS and Android, have a rich push notification system that allow for interactivity and rich media in some cases. However, there is a disconnect as applications have to support multiple vendors that all support a slightly different push notification format. Notifications are important for a quality application as they help to keep the user informed about the things they care about most. The “Glance and Go” marketing campaign by Microsoft a number of years back for Windows Phone, whilst ultimately a failure (bye bye Windows Phone, we’ll miss you) it rang true in that notifications and badges are an extremely effective way of keeping users abreast of background activity within applications (either locally on the device, or remotely)

Hopefully from this breakdown you can see that PWAs, whilst one of the hottest topics today, is far from “a new way to deliver amazing user experiences,” since application developers have been doing this since before the release of the iPhone. I guess the big distinction with PWAs is the “on the web”…. as in “please developers, stop building web sites with a crappy user experience, and start building rich applications that delight the user”. Perhaps some day we’ll break the dependency on the request-response model that has for so long governed the design of web sites.

App or not to App

Following my last post there were a couple of interesting tweets that made me revisit (again) the discussion of whether building an app is the right thing to do. For example, @GeoffreyHuntley said:

Decision time:
- #0 Don't make an app unless you absolutely have to.
- #1 React + React Native (insane productivity)
- #2 Xamarin (stagnating tbh)
- #3 Flutter (innovator - watch this space)

To be blunt, options 1-3 are all semi-painful – I’m not going to go into detail as to why, as that’s not the point of this post but needless to say that each one has their pros and cons, and none are what you’d consider an ideal development experience. Option 0 sounds like a great option and with the rapid development of Progressive Web Applications (with service workers being included by both React and Angular) it really does seem that not having to build an app is the way to go.

Ok, but in that case, when would we build an application? Before we answer this, I think it’s worth revising what the notion of an “application” or “app” actually means. If you do a search for “App” on Wikipedia you get a number of responses:

  • Mobile app, software designed to run on smartphones and other mobile devices
  • Application software that causes a computer to perform tasks for computer users
  • Web application or web app, software designed to run inside a web browser

(And particular note that the term “website” is not included here as according to Wikipedia a website is “a collection of related web pages” – personal opinion: if you still building for the web using the traditional post-back model (yes, looking at you ASP.NET) you’re building a website, not an app).

Let’s ignore for the moment the distinction between mobile, web or any other qualifier about the type of an application or the target platform and instead, let’s focus on what an application is. According to Wikipedia an Application is software that causes a computer to perform tasks for a user. This is a pretty wide definition and essentially encompasses most software, whether it be a command line application, browser or window based application. However, if you were to ask most people what they thought an “App” was today, they’d probably give an answer that relates to installing an application from the Apple, Google or Windows Store – it seems like the notion of an App is in somehow attached to the distribution model.

If we look further into this, there are a variety of distribution models:

- An application that you simply download from the Internet and just run (it might download as a Zip file but the important distinction here is that there’s no installation process and no Store managing the application). This is by far the simplest distribution model. However, these days few applications are distributed this way as most operating systems distrust downloaded files from the Internet and will refuse to run them without them being “unblocked” first.

- An application you download from the Internet and then install. For Windows and MacOS historically this was the most common way for applications to be distributed. The operating system didn’t have a built in distribution mechanism, such as a Store, but they did support a model for applications to be installed and uninstalled. The danger of this model, is that, similar to just downloading and running an application, an application that is installed could have wide-reaching access to the host operating system. Over time this model has be adapted and additional security (for example User Account Control on Windows) limited what an installed application could do

- An application you install from a Store. Whilst this model did exist prior to the iPhone, it wasn’t really until the App Store launched that the notion of a single curated Store became mainstream. Now, most platforms have a Store where you can browse, search and install apps to suit your every need. Depending on the platform, the process for submitting, certifying and publishing applications varies, with different levels of quality and policy controls imposed in order to try to maintain a high quality bar for apps. The Store also takes on responsibility for distributing updates to application as they become available, as well as providing a mechanism for developers to charge for their applications.

- An application you load in the browser. Most people don’t really consider websites that they navigate to in the browser as applications. However, websites are becoming highly functional and most no longer require a full post-back in order to load more content, improving the usability. In fact, browsers have tried to prompt web sites as pseudo-apps by allowing users to add a web site to a list of applications (for example the “Apps” icon that appears within Chrome under the address bar).

image

- An application you install via the browser. In contrast to adding a website to a list of applications within the browser, installing a website via the browser allows the website to take advantage of a lot of the benefits of applications installed via a Store. They can appear as an icon on the home screen (or list of applications installed on the device); they run without the browser chrome; they can receive push notifications and much more.

So the question is whether the distribution model is what defines what an “App” is?

When we embark on building an application do we need to lock ourselves into one of these distribution models, or can we pick multiple, or all of these distribution models. Or, is the distribution model different for each platform? To answer this we really need to consider the pros and cons of each mechanism and the corresponding audience reach it gives us, and whether it makes sense to choose a particular distribution model.

Cross-platform applications – PhoneGap/Cordova, Xamarin, PWAs and now Flutter

At Built to Roam we build applications that target a wide array of different platforms, using a wide variety of technologies depending on the project requirements. One of the most challenging things faced by organisation looking to build any form of software is often not what should I build, it’s often what technology should I use to build it. Unfortunately this is also where the most cycles are wasted and the poorest decisions are made.

Nirvana would be building the software once, and for it to be available on every platform and device type, able to be instantly updatable and have a rich and engaging user interface (and I’m sure there’s more things that needed to be bolted onto this list of “ideals”). However, the reality is that there are different device types and sizes; there are different technologies with differing capabilities; and different developer and deployment workflows. Rather than being able to make an absolute decision on the best strategy, companies are limited by their own field of influence. Too often this includes Gartner reports, media hype and both internal and contractors with whom the decision makers have a relationship with.

In addition to the number of options that are available, the optimum strategy also evolves over time. For example, five years ago in Australia it made sense for organisations to start their investment in mobile apps with a fairly basic iPhone application. Today the market expectation is that a mobile strategy encompasses at least Android and iOS, phone and tablet, and with a comprehensive set of features. In fact some applications, don’t even have a web presence, finding that their mobile apps were sufficient for their business model.

So the question is really whether it is possible to define the optimum strategy for a business and is it possible to future proof it?

To investigate this a bit further, let’s take a look at the progression of native application development. What’s quite interesting is that businesses have woken up to the fact that maintaining multiple applications written in the preferred technology for each platform is not sustainable. This has led to the emergency of a host of cross platform tools that generate native applications. There are tools such as Xamarin/Xamarin Forms which compile C# so that it can be run on the target platform; There has also been an explosion in Javascript based solutions, such as React Native where it generates the native components for each platform based on HTML mark-up (+CSS, JavaScript etc); More recently again there is Flutter, which aims to provide a user experience that has been drawn from the ground up to be platform agnostic. How do you make a decision between these technologies?

More importantly is – are you making the decision about the right thing? It would seem that making a decision about which native application toolset to use would be right but actually the web and some of the hybrid solutions solve so many challenges that native application developers face, it would be foolish to ignore them. Take for example the recent hype around Progressive Web Applications. There are some who believe this is just another round of hype about the newest buzzword to arrive on the scene but in actual fact whilst the name is new, the concept is not. Back even in the days of Windows Vista, there were desktop gadgets that essentially allowed parts of the web to run in a container in an offline capacity. PWAs are just the latest name to be given to this concept.

Where PWAs are set to make a difference is that they are being widely backed (eg Google: https://developers.google.com/web/progressive-web-apps/ and Microsoft: https://pwabuilder.com) and they also arrive at a point in time where devices have browsers and rendering engines that are capable of delivering a high-performance web experience whether in-browser, or in a hosted web application.

Do you think the market is ready for PWAs? or are native applications going to rule for the foreseeable future?

New BuildIt Release for NetStandard 2.0 (General, States and Forms)

A new release of the following libraries is available via NuGet (v1.1.0.134):

- BuildIt.General

- BuildIt.States

- BuildIt.Forms

Whilst not much has changed in terms of features, behind the scenes there was quite a significant change as we adjusted the solution/project structure, and thus the nuget package structure. We took advantage of the ability to multi-target which meant we no longer have to have separate projects/libraries in order to support platform specific features. BuildIt.General, which used to have a UWP specific library, is now a single libary. Same goes for BuildIt.States. BuildIt.Forms has two libraries, down from the 5 that it used to have.

Additionally we also added direct support for netstandard 2.0. As part of the build process, each library is compiled for netstandard 1.0, netstandard 2.0 and then any platforms that have additional features.

In this release we’ve released multiple packages with the same version number, even though there is an interdependency between them (Forms –> States –> General).

Please reach out and let me know if you see any issues in this release with any of these libraries. We’ll be working to release updates to the other BuildIt libraries over the coming weeks.

Building Applications for Platform X

As we get started with a new year it’s time to pause and think about how the app development ecosystem has evolved, what technologies continue or are emerging, and look at the decision matrix that will define what technology your next application is developed in. I’m going to treat this post as a bit of an intro to some of the technologies that I think are worth further investigation.

I think the easiest way to do this is to walk the spectrum from web apps through to native platform apps:

Web Apps

When we talk about web apps, there is a natural assumption that these will be responsive web sites that will work across a wide range of devices and browsers. However, they can be divided further into what I would consider traditional web sites and single page applications. Whilst this division can be blurred, for example when you host an Angular application within a .NET core application, the point is that there is a difference in the mindset of the developers building the web app.

Of course, this section includes the obvious ASP.NET Core, React and Angular. Whilst ASP.NET is still a valid choice, I specifically left it out of the list as I think most new projects will favour ASP.NET Core unless there is an impediment that requires full ASP.NET.

Progressive Web Applications allow web developers to extend their applications to leverage more device capabilities. This is a particularly hot area of development for most platforms as this is seen as one of the best long term solution for minimising mobile development fatigue.

Hybrid

Next in the progression are hybrid applications which combine web technologies with a platform specific deployment package – this sounds a bit cryptic but that’s because there are a couple of different models for this.

Firstly there’s the Cordova/PhoneGap model where the application is defined using html, css, javascript, and wrapped in a native platform deployment package. The deployment step is required in order for most stores to accept applications. The important thing here is that the layout and logic for the application is packaged with the application and that the platform web rendering engine is used to display the application.

The second model is much more interesting and is one that’s being used by React Native and Native Script where the logic and layout is defined in javascript, css and a form of HTML. The HTML actually defines native elements that will be rendered in the correct location.

Cross Platform

Before we get to native platform tools and technologies, we’ll stop in on a long time friend, Xamarin. As with the previous sections there are again two options with Xamarin: traditional Xamarin, and Xamarin Forms. With the traditional Xamarin approach the developer is much closer to the metal and has a higher degree of control. However, the Xamarin Forms option allows for user interfaces to be rapidly developed once, and then feedback/issues are resolved on a platform by platform basis.

Native Platform

Lastly, we have the Native platform options for developers:

Android

Java, C++ with Eclipse, Android Studio

iOS

Objective C, Switft, Interface Builder (now part of XCode)

UWP

C#, XAML, Visual Studio (or Visual Studio for Mac)

As this is hopefully one in a sequence of posts on the topic of framework selection, I’d love some feedback on what technology you think will be important to you and those you work with – comments are off but hit me up on twitter @thenickrandolph if you have thoughts on this.

Making MvvmCross with Xamarin Forms Friction Free

My last two posts (part 1 and part 2) outlined all the steps necessary to get a new Xamarin Forms with MvvmCross project setup. What I thought was going to be a simple post ended up being much longer due to all the unnecessary steps to setup both Xamarin Forms and MvvmCross. I’ve recently been contributing a little to MvvmCross and one of my concerns with it is that there are just way to many things that you need to get right in order to get it to work nicely with Xamarin Forms. If you don’t follow one of the introductory posts, such as the one provided by Martjin van Dijk, you’ll probably start hacking around with the numerous extension points in order to get it to work. I spent time over the last day seeing if I could reduce this initial friction to getting started.

When you adopt a framework, or any library for that matter, you do so to reduce the need to reinvent the wheel – there’s no point in recreating, or creating something new, if there are existing solutions available. However, I’m of the opinion that you should be able to determine how much the framework influences the way that your code is structured. You should only have to modify your code if the framework offers a clear advantage. If we do a quick review of some of the changes required to take advantage of MvvmCross in our Xamarin Forms project you’ll see that quite a few of these are artificial requirements, mandated by the current MvvmCross implementation, rather than for any specific need. Here are just a couple:

  • App needs to inherit from MvxFormsApplication – this doesn’t add anything other than a couple of events, so unless you want to use those events, this is unnecessary
  • All pages need to inherit from the Mvx equivalent (eg MvxContentPage instead of ContentPage) – the Mvx equivalent expose a ViewModel property which can be useful but is not required in order to take advantages of data binding to the corresponding ViewModel since all Forms elements have a BindingContext that’s used for this purpose. The actual requirement here is for views/pages to implement IMvxView but unless you need the ViewModel property this shouldn’t be a requirement.
  • You need to create a class that inherits from MvxApplication which can do things like register services but most importantly defines what the starting ViewModel is going to be. This is kind of unnecessary if the only thing that it’s doing is defining the starting ViewModel, although I do understand the desire to have the starting ViewModel defined somewhere that is independent of the head projects.
  • All ViewModels need to inherit from MvxViewModel or implement IMvxViewModel – again this is somewhat unnecessary since ViewModels should just be a regular class. Now I do agree that in most cases your ViewModel is likely to implement INotifyPropertyChanged, so this additional requirements isn’t a massive addition but needless to say it shouldn’t be a requirement.

Ok, so after a bit of experimenting without modifying MvvmCross or MvvmCross.Forms (ie I’m just using the NuGet packages) what I came up with is BuildIt.MvvmCross.Forms (currently in prerelease!) which is a NuGet package which adds a couple of helper classes to get you going just that bit quicker. Here are the steps to get started using BuildIt.MvvmCross.Forms:

Start by following the steps outlined in part 1 – this will give you a Xamarin Forms project that’s completely up to date. I’ll call this project LowFriction

Next, follow the early steps in part 2 to add an additional project for your ViewModels, LowFriction.Core, and subsequently add references to MvvmCross (to all projects) and MvvmCross.Forms (to all projects except the Core project).

Add a reference to the BuildIt.MvvmCross.Forms NuGet package to all projects except the Core project. A primary requirement here is that the Core project should not have a reference to the view technology, which in this case is Xamarin Forms – if you find yourself adding a reference (directly or otherwise) to Xamarin Forms to your Core project, you’ve done something wrong and you should rethink the decisions that led you to that point.

You still need to change App.xaml to inherit from MvxFormsApplication – I couldn’t find a work around this requirements

Your pages do not need to change to implement iMvxView – MainPage inherits from ContentPage

In your Core project you will need to create ViewModels that map to your pages, and they need to implement iMvxViewModel – again I couldn’t find a work around for this requirement. MainViewModel inherits from MvxViewModel.

In your Core project you do not  need to create a class that inherits from MvxApplication – we’ll come to this later but essentially BuildIt.MvvmCross.Forms has class called TypedMvxApplication whose type parameter is the starting ViewModel. If you do want to extend the MvxApplication you can still create your own application but I would recommend using TypedMvxApplication as a starting point

UWP

In App.xaml.cs replace

Xamarin.Forms.Forms.Init(e);

with

var setup = new SetupFromViewModel<MainViewModel, LowFriction.App>(rootFrame, e);
setup.Initialize();

You can see here that the SetupFromViewModel class accepts the starting ViewModel as a parameter. If you’d prefer to define the starting ViewModel in the Core project I recommend defining a class that inherits from TypedMvxApplication, specify the starting ViewModel as the type parameter, and then use the SetupFromApplication class in App.xaml.cs.

Change MainPage to inherit from BuildIt.MvvmCross.Forms.UWP.MvxFormsWindowsPage (I also updated the layout of MainPage to show some data coming from databinding from the ViewModel, similar to what I did in my previous post)

Change the MainPage constructor to

public MainPage()
{
     this.InitializeComponent();

    MvxLoadApplication();
}

Android

Change MainActivity to inherit from CustomMvxFormsAppCompatActivity<SetupFromViewModel<MainViewModel, LowFrictionApp>, MainViewModel>

Comment out the Xamarin Forms init code:

//global::Xamarin.Forms.Forms.Init(this, bundle);
//LoadApplication(new App());

iOS

Change AppDelegate to inherit from CustomMvxFormsApplicationDelegate

Change FinishedLaunching

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
     Window = new UIWindow(UIScreen.MainScreen.Bounds);

    var setup = new SetupFromViewModel<MainViewModel, App>(this, Window);
     setup.Initialize();

    MvxLoadApplication();

    Window.MakeKeyAndVisible();

    //global::Xamarin.Forms.Forms.Init();
     //LoadApplication(new App());

    return base.FinishedLaunching(app, options);
}

And we’re done! Build and run on each platform and you should be good to go.

As you can see there are significantly fewer steps involved in getting started, and few additional classes to be created. I do note that there is still room for improvement and I feel that as frameworks go MvvmCross has been developed with extensibility in mind – which is why I was able to streamline the getting started experience so much.

Getting Started: MvvmCross with Xamarin Forms (Part 2)

In my previous post I covered the first part of this post on Getting Started with MvvmCross and Xamarin Forms where I covered the initial steps in getting a new Xamarin Forms project started. In this post I’m going to continue on and show how you can configure a Xamarin Forms solution to make use of MvvmCross.

Before I get started with MvvmCross I’m going to add a new project which will contain all my ViewModels. Whilst not entirely necessary, particularly with Xamarin Forms where the views/pages are in a .NET Standard library, it’s good practice to completely separate your ViewModels away from the views/pages to avoid any accidental interdependencies forming. I’ll add a new project based on the .NET Standard class library template.

image_thumb11[1]

For this library I’m going to adjust the .NET Standard version back to 1.0 – I prefer to start with a low .NET Standard version and increase it only when I need to take advantage of features in the higher versions. This ensures that the library can be referenced by the widest set of targets platforms.

image_thumb11

I’ll add a reference to the new project to each of the other projects in the solution.

image_thumb31

The next step is to add a reference to the MvvmCross NuGet package. Currently MvvmCross is still distributed as a set of Portable Class Libraries and if we attempt to add the NuGet package to either our MvvmcrossGettingStarted or MvvmcrossGettingStarted.Core projects, we’ll get an error as they’re both .NET Standard library. What’s annoying about this is that the MvvmCross PCLs are fully compatible with .NET Standard, meaning that it should be possible to add a reference to them. Unfortunately Visual Studio isn’t clever enough to be able to resolve this, and as such we need to adjust the csproj files for both projects before attempting to add a reference to MvvmCross.

Add the following line into the first PropertyGroup of the csproj files for both MvvmcrossGettingStarted or MvvmcrossGettingStarted.Core projects. One saving grace is that it’s now easy in Visual Studio to edit a csproj by right-clicking on the project and selecting “Edit <project name>.csproj”.

<PackageTargetFallback>$(PackageTargetFallback);portable-net45+win8+wpa81</PackageTargetFallback>

Eg.

image_thumb23

Next we can go ahead and add a reference to MvvmCross to all our projects. Right-click on the solution node in Solution Explorer and select Manage NuGet Packages for Solution, and then search for mvvmcross. Select the most recent stable version of MvvmCross (this image is a little old as the version is at 5.6.3 at time of writing this)

image_thumb9

In addition to the main MvvmCross package, we also want to add in the Xamarin Forms support library, MvvmCross.Forms. Note that we do not add this to the MvvmcrossGettingStarted.Core project – this is the separation of concerns we setup at the beginning of this post to ensure there is no dependencies on the viewing technology within our ViewModels.

image_thumb21

Now that we have added the references to MvvmCross there are a bunch of small changes we need to apply to our application in order to get it all up and running. We’ll start in the MvvmcrossGettingStarted.Core project where we need to create two classes.

The first class we’ll create inherits from MvxApplication and is used to setup the application within the ViewModel world. MvvmCross has an opinionated navigation model whereby navigation is defined at a ViewModel level, and simply implemented at a View level. As such the MvxApplication class, in this case GettingStartedApplication, defines the first ViewModel for the application.

public class GettingStartedApplication : MvxApplication
{
     public override void Initialize()
     {
         RegisterNavigationServiceAppStart<MainViewModel>();
     }
}

The second class is the ViewModel that matches the first view or page of the application. MainPage was created back when we created the Xamarin Forms application, so we’ll create a class called MainViewModel. Whilst you can override the default view to viewmodel mapping in MvvmCross, it’s preconfigured to align views and viewmodels based on a naming convention. I typically stick with XXXViewModel and XXXPage but XXXView is also supported out of the box.

In this case MainViewModel exposes a simple property that we’ll data bind to later to show that the Page and ViewModel have been glued together correctly.

public class MainViewModel: MvxViewModel
{
     public string WelcomeText => "Welcome to my data bound Xamarin Forms + MvvmCross application!";
}

Now we’ll switch over to the MvvmcrossGettingStarted project and make some changes to both the App and MainPage classes.

In the App.xaml, we need to change the root element to reference MvxFormsApplication

<?xml version="1.0" encoding="utf-8" ?>
<mvx:MvxFormsApplication xmlns="
http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                     xmlns:mvx="clr-namespace:MvvmCross.Forms.Platform;assembly=MvvmCross.Forms"
                    
x:Class="MvvmcrossGettingStarted.App">
     <Application.Resources>
     </Application.Resources>
</mvx:MvxFormsApplication>

And in App.xaml.cs, remove the inheritance – the Microsoft templates insist on including the inheritance in both the xaml and xaml.cs files which is quite unnecessary and should be removed.

public partial class App
{
     public App()
     {
         InitializeComponent();
     }
}

We need to make a similar change to MainPage.xaml, changing the root element to MvxContentPage. We’ll also change the Label to use data binding to return the WelcomeText property from the MainViewModel.

<?xml version="1.0" encoding="utf-8" ?>
<mvx:MvxContentPage xmlns="
http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                     xmlns:local="clr-namespace:MvvmcrossGettingStarted"
                     xmlns:mvx="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
                    
x:Class="MvvmcrossGettingStarted.MainPage">
     <Label Text="{Binding WelcomeText}"
            VerticalOptions="Center"
            HorizontalOptions="Center" />
</mvx:MvxContentPage>

Again, remove the inheritance specified in MainPage.xaml.cs

public partial class MainPage
{
     public MainPage()
     {
         InitializeComponent();
     }
}

The next step involves adding a Setup class to each of the head projects, and then creating an instance of the Setup class to invoke MvvmCross when the application starts up.

UWP

The UWP Setup inherits from MvxFormsWindowsSetup and unlike the Android and iOS Setup classes, the UWP Setup needs to override the default log behaviour by setting the log provider type to None and then creating an instance of the EmptyVoidLogProvider  (the implementation of this is coming up soon) – this should be fixed in a future MvvmCross version.

public class Setup : MvxFormsWindowsSetup
{
     public Setup(Frame rootFrame, LaunchActivatedEventArgs e) : base(rootFrame, e)
     {
     }

    protected override MvxLogProviderType GetDefaultLogProviderType() => MvxLogProviderType.None;

    protected override IMvxLogProvider CreateLogProvider() => new EmptyVoidLogProvider();

    protected override IEnumerable<Assembly> GetViewAssemblies()
     {
         return new List<Assembly>(base.GetViewAssemblies().Union(new[] { typeof(MvvmcrossGettingStarted.App).GetTypeInfo().Assembly }));
     }

    protected override MvxFormsApplication CreateFormsApplication() => new MvvmcrossGettingStarted.App();

    protected override IMvxApplication CreateApp() => new Core.GettingStartedApplication();
}

Now in App.xaml.cs we need to replace

Xamarin.Forms.Forms.Init(e);

with

var setup = new Setup(rootFrame, e);
setup.Initialize();

And in Main.xaml.cs replace

LoadApplication(new MvvmcrossGettingStarted.App());

with

var start = Mvx.Resolve<IMvxAppStart>();
start.Start();

var presenter = Mvx.Resolve<IMvxFormsViewPresenter>() as MvxFormsUwpViewPresenter;
LoadApplication(presenter.FormsApplication);

Finally, we need to add the EmptyVoidLogProvider

public class EmptyVoidLogProvider : IMvxLogProvider
{
     private readonly EmptyVoidLog voidLog;

    public EmptyVoidLogProvider()
     {
         voidLog = new EmptyVoidLog();
     }

    public IMvxLog GetLogFor<T>()
     {
         return voidLog;
     }

    public IMvxLog GetLogFor(string name)
     {
         return voidLog;
     }

    public IDisposable OpenNestedContext(string message)
     {
         throw new NotImplementedException();
     }

    public IDisposable OpenMappedContext(string key, string value)
     {
         throw new NotImplementedException();
     }

    public class EmptyVoidLog : IMvxLog
     {
         public bool Log(MvxLogLevel logLevel, Func<string> messageFunc, Exception exception = null, params object[] formatParameters)
         {
             return true;
         }
     }
}

Now when we build and run the UWP project we can see that the MainPage is shown and is data bound to the MainViewModel.

image

iOS

The iOS Setup is the simplest out of the three platforms.

public class Setup : MvxFormsIosSetup
{
     public Setup(IMvxApplicationDelegate applicationDelegate, UIWindow window)
         : base(applicationDelegate, window)
     {
     }

    protected override IEnumerable<Assembly> GetViewAssemblies()
     {
         return new List<Assembly>(base.GetViewAssemblies().Union(new[] { typeof(MvvmcrossGettingStarted.App).GetTypeInfo().Assembly }));
     }

    protected override MvxFormsApplication CreateFormsApplication() => new MvvmcrossGettingStarted.App();

    protected override IMvxApplication CreateApp() => new Core.GettingStartedApplication();
}

In AppDelegate we need to change the inheritance from  global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate to MvxFormsApplicationDelegate and change the FinishedLaunching method as follows:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
     Window = new UIWindow(UIScreen.MainScreen.Bounds);

    var setup = new Setup(this, Window);
     setup.Initialize();

    var startup = Mvx.Resolve<IMvxAppStart>();
     startup.Start();

    LoadApplication(setup.FormsApplication);

    Window.MakeKeyAndVisible();

    return base.FinishedLaunching(app, options);
}

Now we’re good to build and run the iOS project

image

Android

Lastly, add Setup to the Android project. Note this is slightly different from the iOS and UWP projects in that the GetViewAssemblies method excludes the assembly for the Android head project. This is to avoid the MainActivity being added as a view, that based on our naming convention would match with MainViewModel giving a duplicate when attempting to resolve the View that should be rendered.

public class Setup : MvxFormsAndroidSetup
{
     public Setup(Context applicationContext) : base(applicationContext)
     {
     }

    protected override IEnumerable<Assembly> GetViewAssemblies()
     {
         return new List<Assembly>(base.GetViewAssemblies()
             .Union(new[] { typeof(MvvmcrossGettingStarted.App).GetTypeInfo().Assembly })
             .Except(new[] {this.GetType().Assembly})
             );
     }

    protected override MvxFormsApplication CreateFormsApplication() => new MvvmcrossGettingStarted.App();

    protected override IMvxApplication CreateApp() => new Core.GettingStartedApplication();
}

The MainActivity needs to be updated to change its inheritance from global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity to MvxFormsAppCompatActivity<MainViewModel>. And the OnCreate needs to be updated to

[Activity(Label = "MvvmcrossGettingStarted", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : MvxFormsAppCompatActivity<MainViewModel>
//global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
     protected override void OnCreate(Bundle bundle)
     {
         TabLayoutResource = Resource.Layout.Tabbar;
         ToolbarResource = Resource.Layout.Toolbar;

        base.OnCreate(bundle);

        var startup = Mvx.Resolve<IMvxAppStart>();
         startup.Start();
         InitializeForms(bundle);

     }
}

Finally the last platform, Android, is good to build and run. Note however that Android has a tendency to be a pain and that after setting everything up correctly you may still run into issues building, deploying and running. Before you waste hours looking at your code to see what you’ve done wrong, make the assumption that the tools are crap – delete both bin and obj folders from the Android head project, and uninstall the application from the device/emulator (assuming it has already been installed). Try building and running again – if this still fails, then you may indeed have something wrong with your code!

image

Getting Started: MvvmCross with Xamarin Forms

Over the past 6-12 months we’ve seen dramatic changes in Xamarin Forms and the support within Visual Studio. The most recent update, which I covered in my previous post, included a number of new features for cross platform developers. However, despite these updates, getting started with cross platform development is still quite complex. In this post I wanted to take the opportunity to reiterate how to start a new Xamarin Forms project. From there I’ll cover adding in MvvmCross and discuss the importance of having a framework that will make development that much easier (for the record MvvmCross isn’t the only option, there are plenty of great alternatives such as Prism and FreshMvvm).

Part 1: Getting Started with Xamarin Forms

Before getting started, make sure you’ve run the Visual Studio Installer and have upgraded to the latest stable release of Visual Studio. The team at Microsoft have been putting a lot of focus on stability and performance, so upgrading to the latest version does help (still not perfect but a marked improvement over this time last year!). Upgrading Visual Studio continually can be a bit of a pain, especially since Microsoft haven’t quite worked out how to automatically download updates in the background for VS – meaning that you have to stop whatever you’re doing whilst the updates download and then install. Recommendation is to run the installer periodically at the end of your day, or when you’re heading to a long meeting; hopefully the installation is complete by the time you return.

Now that you’re all up to date, let’s create a new solution by selecting the Cross-Platform App (Xamarin Forms) template from the New Project dialog. Note that if you don’t see this template, you may have to adjust the workloads you selected in the VS Installer so that you have all the cross-platform development components selected.

image

After clicking OK you should be presented with a second dialog that allows you to specify parameters for how your cross platform project should be setup. As you can see from the image, I recommend always selecting all three platforms (even if you’re only planning on targeting one or two of them initially); In this case we’re going with Xamarin.Forms with a simple Blank App; The last option I’m particularly passionate about – do NOT select Shared Project – for the good of your project, the team and general good programming practice, please select the .NET Standard option for Code Sharing Strategy. At time of writing the .NET Standard option is only available in the preview build of Visual Studio; the stable build uses a Portable Class Library, which is still preferable over using a Shared Project.

image

This time clicking OK will create a new solution.

Unexpected Error when Creating Solution

Unfortunately, at time of writing this post there is also a bug in the current cross platform template that results in the following error:

image

If you see this error, a quick Google will yield the following bugzilla issue (https://bugzilla.xamarin.com/show_bug.cgi?id=60995) which describes the issue, along with how to fix it yourself – you just need to edit the Android csproj file and remove the " from around the TargetFrameworkVersion ie:

replace:

<TargetFrameworkVersion>"v8.0"</TargetFrameworkVersion>

with
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>

After fixing up the csproj file you’ll need to add the existing projects into the solution file.

Assuming you didn’t run into any issues creating the solution, or you were able to fix up the Android csproj file, you should be able to build and run each of the head projects:

UWP

image

Note: When building the UWP project I was seeing a build warning stating “warning APPX0108: The certificate specified has expired.” which I thought was a bit odd since I had just created the project and normally the certificate that is used for debug builds is created alongside the new project. Double-clicking the package.appxmanifest and switching to the Packaging tab I see that the Publisher display name isn’t set correctly – I’m guessing at this point that the cross platform template contains an existing certificate, instead of creating one each time. You can easily fix this by changing the publisher display name, clicking Choose Certificate and then from the dropdown select “Create test certificate”.

image

Now when you build the project you won’t see this warning – I’m guessing this is also a bug in the preview version of the cross platform template.

Android

image

For Android I’m using the Google Android Emulator that can now be installed using the Visual Studio Installer. This is significantly better than it used to be, and the images are much more recent than those for the Visual Studio Android Emulator which has been deprecated now.

iOS

image

For iOS, as I’m working from a Windows laptop, I use the Remote Simulator which works really well and means I don’t need to continually VNC to my MacMini or have to deploy to a real device.

Again there was an issue with the iOS template in that the MinimumOSVersion was set to “11.2” instead of just 11.2 in the Info.plist file.

<key>MinimumOSVersion</key>
<string>11.2</string>

Correcting the MinimumOSVersion will allow your application to run on a device or emulator.


Now that we’ve validated that all the platforms run, it’s time to make sure they’re setup correctly ready for us to add in Mvvmcross and to set the foundation of our application. Android and iOS should be setup correctly, although you may want to double-check to make sure Android is set to use the latest platform version (see Application tab of the Android project properties); UWP defaults to using the Fall Creators Update (FCU) as the minimum version, which is way to recent for applications wanting to target the widest set of customers. Our preferences is to set this back to the November Update

image

Note however, that this does preclude your application from using .NET Standard 2.0 libraries, as these are not compatible with UWP projects prior to the FCU. Unfortunately the .NET Standard library that holds the Xamarin Forms views for the solution is set to .NET Standard 2.0 by default. This is completely unnecessary, so it can be reduced back to 1.4 (or below, depending on your preferences)

image

Next, we want to make sure we’re using the latest NuGet packages – right-click on the solution node in Solution Explorer and select Manage NuGet Packages for Solution

image

After upgrading all the NuGet packages, double-check to make sure all platforms build and run. Now’s a great time to check your solution in to your repository of choice (Note: make sure you check in the pfx file that is part of the UWP solution. You’ll probably have to manually add this file to your repository as most repositories ignore pfx files by default).

Update: Part 2 is now available.

Xamarin Development with Visual Studio 2017 Version 15.5

Normally I don’t bother posting anything about the progressive updates that roll out for Visual Studio 2017 but version 15.5 adds a bunch of new features that are set to make app development using Xamarin just that little bit nicer. Pierce has a great post covering a lot of the relevant updates - https://blog.xamarin.com/whats-new-visual-studio-2017-version-15-5/ 

Over the last 6-12 months the debugging experience for Xamarin applications on both iOS and Android has got significantly better. I posted recently about my discovery that the Google Android emulator was actually quite good (https://nicksnettravels.builttoroam.com/post/2017/10/11/Hey-who-moved-my…-Visual-Studio-Emulator-for-Android.aspx), and whilst the build and deploy process is still painfully slow on Android, it’s definitely getting better. Now with Live XAML Previewing supported in the emulator, at least the iteration whilst making UI changes will be quicker.

I’ve also been using the remote iOS simulator – particularly at home where I use a remote build server that is on the other side of the room, it’s painful to have to deploy to a real device. I have seen some issues where debugging with the remote iOS simulator seems to just lock up but I think that was only an issue in the preview of VS mixed with the latest Windows Insider build (unfortunately neither team seems to care much about stability with their preview builds Sad smile).

Whilst I’m talking about doing iOS development, the other significant improvement in 15.5 is the messaging regarding connecting to the Mac build agent. In the past this has been limited to success/fail; if you wanted any more details you really had to go hunting in the log files (usually it ended up being a result of a mis-match of SDK versions between the build agent machine and the machine with VS installed). The dialog for connecting to the Mac build agent has a nice progress information pane at the bottom that shows what step the connection manager is at and reports any issues – nice work MS, this is really, really useful!

Ok, I can’t end this post without pointing to the fact that Microsoft has finally worked out how to get the elephant out of the corner of the room, and by this I mean the support for PCLs v’s .NET Standard for new projects. Prior to this release if you created a new Xamarin project it would create a PCL for your shared code (and yes, I’m ignoring the Shared Project option, cause this should never be selected), and it was rather painful to have to upgrade it to .NET Standard (see https://nicksnettravels.builttoroam.com/post/2017/08/26/Getting-Started-Xamarin-Forms-with-NET-Standard.aspx if you’re still on an older version of Visual Studio). Now when you create a new Xamarin project you get a .NET Standard library and you can pick which target platform(s) you want to target (I would encourage you to pick all, unless you have a particular reason not to!).

Grab the latest version of Visual Studio 2017 and get coding!

Authentication Redirection Loop with Angular Application and Azure Active Directory

Recently we ran in to some difficulty with an Angular application that was being retrofitted into a different environment. During the initial development the Angular application had been pushed to Azure for testing. However, the final resting place for the application was on a on-premises sever. Whilst the switch was relatively painless, with the only major change being to a persistent file storage instead of blob storage, we also had to shift from our development Azure AD tenant (the Angular application, and the associated services, uses Azure AD to authenticate and authorize users), to the client’s Azure AD tenant. This shift required creating two new application registrations within the client’s Azure AD tenant.

Unfortunately after creating the new registrations, and updating the Angular application (and the corresponding services), any attempt to log in with valid credentials resulted in a continual loop between the Angular application and the Azure AD login prompt. In this case we were only using Azure AD to authenticate users and other than controlling access to the application services there weren’t any other permissions that users would have to agree to.

In the past I’ve posted about how administrators have to grant permission to users within their tenant to access an application (see https://nicksnettravels.builttoroam.com/post/2017/01/24/Admin-Consent-for-Permissions-in-Azure-Active-Directory.aspx). Usually there is an Azure AD login error when users attempt to sign in. In this case, for some reason we either missed the error message or it was being obscured by the automatic redirection between the Angular application and the Azure AD login prompt.

We did end up finding the solution, thanks to the Azure AD team at Microsoft, who quickly identified the error in our Fiddler trace. The critical request/response was:

Request

GET https://login.microsoftonline.com/<tenantid>/oauth2/authorize?response_type=token&client_id=<clientid>&resource=<resourceid>&redirect_uri=<uri>&prompt=none&login_hint=admin

Response

HTTP/1.1 302 Found
Location: <uri>
<html><head><title>Object moved</title></head><body>
<h2>Object moved to <a href="<uri>/#error=interaction_required&amp;error_description=AADSTS65001%3a+The+user+or+administrator+has+not+consented+to+use+the+application+with+ID+%27.+Send+an+interactive+authorization+request+for+this+user+and+resource

The important part is that the error indicates that either the user or administrator has not consented to use of the application, and that there should be an interactive authorization request. This is a little cryptic but going back to my previous post we can simply add “prompt=admin_consent” to the login request – assuming an administrator logs in, they can then grant access to the application to all users in the tenant.

There is actually a much easier way for single tenant applications, which this is. Instead of waiting for an administrator to log in, permission can be granted via the Azure portal:

- Select the Directory where the application is registered (drop down in top right cornert of the Azure portal where the signed in user is listed)

- Select Azure Active Directory from the sidebar menu

- Select App Registrations

- Select the application registration you want to grant access to

- From All settings, click on the Required Permissions link

- Click “Grant Permissions”

image

This will give all users access to the application. If you have multiple registrations (eg one for the web site and one for the corresponding services), don’t forget to grant permission to both registrations.

Again, big thanks to the team at Microsoft for pointing us to the solution

Styling the MediaPlayerElement and MediaTransportControls in a Universal Windows Platform (UWP) Application

In my previous post, Building Media Applications for the Universal Windows Platform (UWP) using the MediaPlayerElement, I covered the basics of building a UWP media application using the MediaPlayerElement. Towards the end of the post I showed how you can override some of the built in behaviour but I was yet to show you how you can adjust the visual style of the player or the controls. In this post I’ll do just that, I’ll show you where to find the built in styles and how to start customizing them, including some gotchas that you should be aware of.

Ok, let’s get started by looking for the built in styles. Whilst Microsoft now do a good job of documenting the built in styles online (for example the styles and templates for the MediaTransportControls element is defined at https://msdn.microsoft.com/en-us/library/windows/apps/mt414180.aspx), there is nothing like looking at what ships in the platform. For this we go to generic.xaml, typically located at C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\10.0.16299.0\Generic – Note that this may vary based on which platform SDK you have installed. Inside generic.xaml I’m going to locate the Style for the MediaPlayerElement:

<Style TargetType="MediaPlayerElement">
     <Setter Property="HorizontalAlignment" Value="Stretch" />
     <Setter Property="VerticalAlignment" Value="Stretch" />
     <Setter Property="IsTabStop" Value="False" />
     <Setter Property="Template">
         <Setter.Value>
             <ControlTemplate TargetType="MediaPlayerElement">
                 <Grid x:Name="LayoutRoot">
                     <Border Background="Transparent" />
                     <Image  x:Name="PosterImage"
                         Visibility="Collapsed"
                         Source="{TemplateBinding PosterSource}"
                         Stretch="{TemplateBinding Stretch}" />
                     <MediaPlayerPresenter x:Name="MediaPlayerPresenter"
                         IsFullWindow="{TemplateBinding IsFullWindow}"
                         Stretch="{TemplateBinding Stretch}"
                         MediaPlayer="{TemplateBinding MediaPlayer}" />
                     <ContentPresenter     x:Name="TransportControlsPresenter"
                         Visibility="{TemplateBinding AreTransportControlsEnabled}" />
                     <Grid x:Name="TimedTextSourcePresenter" />
                 </Grid>
             </ControlTemplate>
         </Setter.Value>
     </Setter>
</Style>

As you can see, the Style for the MediaPlayerElement is made up of a few different components:

  • MediaPlayerPresenter – this is where the actual video content will be displayed
  • ContentPresenter – this is where the player controls will be displayed
  • “TimedTextSourcePresenter” – this is where the closed captions will be presented

Let’s make a subtle change here by adding another Grid immediately after the TimedTextSourcePresenter with a semi-transparent Pink colour and a TextBlock to indicate that this is a customized player.

<Page.Resources>
     <Style TargetType="MediaPlayerElement">
         <Setter Property="HorizontalAlignment"
                 Value="Stretch" />
         <Setter Property="VerticalAlignment"
                 Value="Stretch" />
         <Setter Property="IsTabStop"
                 Value="False" />
         <Setter Property="Template">
             <Setter.Value>
                 <ControlTemplate TargetType="MediaPlayerElement">
                     <Grid x:Name="LayoutRoot">
                         <Border Background="Transparent" />
                         <Image  x:Name="PosterImage"
                                 Visibility="Collapsed"
                                 Source="{TemplateBinding PosterSource}"
                                 Stretch="{TemplateBinding Stretch}" />
                         <MediaPlayerPresenter x:Name="MediaPlayerPresenter"
                                                 IsFullWindow="{TemplateBinding IsFullWindow}"
                                                 Stretch="{TemplateBinding Stretch}"
                                                 MediaPlayer="{TemplateBinding MediaPlayer}" />
                         <ContentPresenter     x:Name="TransportControlsPresenter"
                                                 Visibility="{TemplateBinding AreTransportControlsEnabled}" />
                         <Grid x:Name="TimedTextSourcePresenter" />
                        <Grid Background="Pink"
                                 IsHitTestVisible="False"
                                 Opacity="0.4">
                             <TextBlock Foreground="Black"
                                         Text="Custom Player" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="50,5,5,5"/>
                         </Grid>

                     </Grid>
                 </ControlTemplate>
             </Setter.Value>
         </Setter>
     </Style>
<Page.Resources>

You’ll notice that I’ve added this Style into the Resources dictionary for the page and that it’s an implicit style (ie I haven’t assigned it a Key) which means that any MediaPlayerElement on this page will pick up this style. You can of course set this Style either directly on the MediaPlayerElement itself or even define it in an application level resource dictionary.

image

Note also that the IsHitTestVisible attribute is set on the Grid, otherwise it will block user input to the player controls as the grid sits over the top of the other elements within the MediaPlayerElement control template.

If you recall from my previous post I intercepted the behaviour that steps the video back and forward so that I could customize this behaviour. Of course, this means that the step forward/backward icons aren’t accurate, since I’m not longer stepping back by 10seconds and forward by 30seconds. In order to override the icons on these buttons, I need to override the Style for the MediaTransportControls. Again the default Style can be found in generic.xaml – it’s really long, so I’m not going to copy the whole thing in here. Here’s a cut down version of the Style showing the changes to the FontIcon for the SkipBackwardButton and SkipForwardButton.

<Page.Resources>
     <Style TargetType="MediaTransportControls">
     ...
         <Setter Property="Template">
             <Setter.Value>
                 <ControlTemplate TargetType="MediaTransportControls">
                     <Grid x:Name="RootGrid"
                             Background="Transparent">
             ...   
             <AppBarButton x:Name='SkipBackwardButton'
                          Style='{StaticResource AppBarButtonStyle}'
                          MediaTransportControlsHelper.DropoutOrder='5'
                          Visibility='Collapsed'>
                           <AppBarButton.Icon>
                         
  <!--<FontIcon Glyph="&#xED3C;" />-->
                            <FontIcon Glyph="&#xF100;"
                                      FontFamily="FontAwesome" />

                           </AppBarButton.Icon>
                         </AppBarButton>
                         ...
                         <AppBarButton x:Name='SkipForwardButton'
                          Style='{StaticResource AppBarButtonStyle}'
                          MediaTransportControlsHelper.DropoutOrder='5'
                          Visibility='Collapsed'>
                           <AppBarButton.Icon>
                         
  <!--<FontIcon Glyph="&#xED3D;" />-->
                            <FontIcon Glyph="&#xF101;"
                                      FontFamily="FontAwesome" />
                           </AppBarButton.Icon>

                         </AppBarButton>
                     </Grid>
                 </ControlTemplate>
             </Setter.Value>
         </Setter>
     </Style>
</Page.Resources>

You might be wondering where I got the new hex code for the FontAwesome font. Rather than go online and having to hunt down hex values for the different characters within a font, if you open Word and go to Insert, Symbol, you can then select the Font and select the character you want. In the lower right corner it states what the Character code is. Remember that you need to make sure the font exists on the computer you’re going to run the application on, so you may want to consider including the font within your application if you pick a non-standard font.

image

Ok, so running the application now, we can see the updated skip backward and skip forward buttons:

image

Unfortunately, here lies a major bug in the implementation of the MediaPlayerElement – if you press the full screen button, you’ll see that the Style for the MediaTransportControls has reverted back to the built in style.

image

This happens because when the video runs in full screen, the MediaTransportControls are being hosted in a separate visual tree to the main part of the application - you can see this if you look at the Live Visual Tree.

image

So, the question is how to handle this? Well the good news is that it’s surprisingly simple. What’s happening is that as the MediaTransportControls are being attached to a different visual tree, they’re not able to resolve the Style defined within the scope of the page. Moving the custom Style for the MediaTransportControls to an application level resource fixes this issue.

<Application
     x:Class="PlayerSample.App"
     xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     RequestedTheme="Light">
     <Application.Resources>
         <Style TargetType="MediaTransportControls">
         ...
         </Style>
     </Application.Resources>
</Application>

The documentation online at https://docs.microsoft.com/en-us/windows/uwp/controls-and-patterns/custom-transport-controls indicates that you should use an explicit style – two things a) this doesn’t fix the full screen issue; you must define the Style at an application level regardless of whether you make it an explicit or implicit style and b) you can make the choice yourself whether to use an implcit or explicit style, depending on whether you want multiple different player styles (ie where an explicit style makes sense).

Building Xbox One applications with the Universal Windows Platform

When building a Universal Windows Platform application there are times when you’ll want a different layout/functionality for a particular platform. For the most part building applications across desktop and phone, other than dealing with different screen sizes and orientation, as a developer you can rely on a similar interaction model: mouce clicks and taps equate to roughly the same interaction for most applications. However, this is not the case with the Xbox – the interaction model using either the media remote or a controller relies on a focus state moving around the screen, followed by pressing the action button to select the currently focussed item. In addition to making sure that every control has an appropriate “in focus” visual, it’s essential to make sure that the flow of focus makes sense and that the user can’t get lost in the application (eg nothing focussed, or nothing appearing to be in focus, on the screen).

The different interaction model between desktop/mobile and Xbox means that you’ll often want to present a different layout, or perhaps expose different functionality on Xbox. There are a number of ways to handle this both in XAML and in code:

1. [C#] The device family can be detected using DeviceFamily property. This returns values such as Windows.Mobile, Windows.Desktop and Windows.Xbox which can be used to define business logic that may be platforms specific. Note that the family name for Surface Hub is Windows.Team

var family = Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily

2. [XAML] The device family can be used to trigger different visual states. There are a number of state triggers that have been packaged together as a NuGet package - https://github.com/dotMorten/WindowsStateTriggers.

<VisualStateManager.VisualStateGroups>
     <VisualStateGroup x:Name="PlatformStates">
            <VisualState x:Name="Xbox">
             <VisualState.Setters>
                 <Setter Target="textBlock.(TextBlock.Text)"
                         Value="Running on Xbox" />
             </VisualState.Setters>
             <VisualState.StateTriggers>
                 <WindowsStateTriggers:DeviceFamilyStateTrigger DeviceFamily="Xbox" />
             </VisualState.StateTriggers>
         </VisualState>
         … other platform states …
     </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

3. [XAML] Use different XAML files for each device family

Main.xaml  // The default XAML file

Main.DeviceFamily-Xbox.xaml  // An Xbox specific XAML file defined within the file name

/DeviceFamily-Xbox/Main.xaml // An Xbox specific XAML file defined using a folder to group together platform specific files.

Using these three different methodds might seem easy enough at first but you start to realise how frustrating it is when you want to work on a specific feature (for example navigation) but you don’t have a specific device with you (for example there’s no Xbox nearby for running the app on). To at least partial solve this problem, here are three tips that will allow you to work on your Xbox app on your desktop.

1. [C#] Instead of referencing the AnalyticsInfo class, we can add a wrapper class that allows us to override the device family whilst debugging the application. Use DeviceInfo.DeviceFamily instead of AnalyticsInfo.VersionInfo.DeviceFamily

#if DEBUG
#define DEBUG_PLATFORM_XBOX
#endif

public static class DeviceInfo
{
     public static string DeviceFamily
     {
         get
         {
#if DEBUG_PLATFORM_XBOX
             return "Windows.Xbox";
#else
             return AnalyticsInfo.VersionInfo.DeviceFamily;
#endif
         }
     }
}

In this case the compilation constant DEBUG_PLATFORM_XBOX is used to override the actual DeviceFamily value. Note we’ve wrapped this using a #if for the DEBUG constant – this prevents the override accidentally being deployed as part of a release build.

2. [XAML] The DeviceFamilyStateTrigger (see https://github.com/dotMorten/WindowsStateTriggers/blob/master/src/WindowsStateTriggers/DeviceFamilyStateTrigger.cs) uses the DeviceFamily returned by the AnalyticsInfo class. A clone of this trigger can be made that relies on DeviceInfo.DeviceFamily (from [1]); this would activate states based on the overridden device family value.

3. [XAML] In order to debug the Xbox layout (eg MainPage.DeviceFamily-Xbox.xaml) on a desktop machine, simply rename the file to specify the Desktop device family (ie MainPage.DeviceFamily-Desktop.xaml).

Combining these three tips allows for the majority of the application to look and feel like it would when running on an Xbox. Unfortunately some of the built in components do render differently on desktop and xbox – they will always render as per the actual device family, despite attempts to override this value.

Building Media Applications for the Universal Windows Platform (UWP) using the MediaPlayerElement

Over the past couple of years at Built to Roam we’ve built a number of media applications. Back when UWP was first launched, all media was played using the MediaElement, which was fairly familiar to XAML developers as it’s been the core element for any video or audio playback on Windows and Windows Phone for quite some time. Unfortunately the built in controls on the MediaElement were not easily stylable, resulting in most developers switching to using the Player Framework, which provided a host of capabilities out of the box such as closed captions, stylable regions and controls, and nice viewmodel architecture that made data binding easy.

Fast forward a year and a bit, and there’s a new player in town, literally. The MediaPlayerElement is a new control that shipped with the Anniversary update (v10.0.14393.0) and is definitely the control that you want to use if you want to do fancy things, such as a persistent video overlay where playback continues as the user continues to navigates throughout the application – this can be achieved by detaching the internal MediaPlayer from one MediaPlayerElement and attach it to another. It’s important to note that whilst the MediaPlayerElement has been around since the Anniversary update, features have been added in both the Creators update and more recently the Fall Creators update, so make sure you take a look at the documentation to make sure you are using features that align with the minimum and target versions you have set for your application.

In this post we’re going to look at the basics of using the MediaPlayerElement and how you can alter its styling. I’m going to start with a new UWP project, selecting the Creators update as the minimum version and the Fall Creators update as the target version. The MediaPlayerElement can be super simple to use – for example the following code is the simplest way to add video to a page that will automatically start playing.

<MediaPlayerElement Source="http://sample-videos.com/video/mp4/240/big_buck_bunny_240p_30mb.mp4"  AutoPlay="True"/>

By default the MediaPlayerElement doesn’t show any of the typical playback controls you’d expect, instead it’s just a raw video canvas that can be used to render video anywher on a page or control. In order to enable the default controls, you simply need to add the AreTransportControlsEnabled attribute set to true (I’ve removed the AutoPlay attribute as there are now going to be playback controls that can be used to start/stop video etc)

<MediaPlayerElement Source="http://sample-videos.com/video/mp4/240/big_buck_bunny_240p_30mb.mp4"  AreTransportControlsEnabled="True"/>

The following image shows the default controls with Progress Bar, Play/Pause, Volume, Aspect Ratio, Cast and Full screen buttons and as you’d imagine, they’re all connected to the appropriate action.

image

But what about other controls like fast forward/rewind, skip forward/backward etc. To customise what controls appear you need to override the TransportControls attribute on the MediaPlayerElement:

<MediaPlayerElement Source="http://sample-videos.com/video/mp4/240/big_buck_bunny_240p_30mb.mp4"
                     AreTransportControlsEnabled="True">
    <MediaPlayerElement.TransportControls>
         <MediaTransportControls IsSkipForwardButtonVisible="True"
                                 IsSkipBackwardEnabled="True"
                                 IsSkipBackwardButtonVisible="True"
                                 IsSkipForwardEnabled="True"
                                 IsFastForwardButtonVisible="True"
                                 IsFastForwardEnabled="True"
                                 IsFastRewindButtonVisible="True"
                                 IsFastRewindEnabled="True" />
     </MediaPlayerElement.TransportControls>

</MediaPlayerElement>

Here I’ve set the TransportControls attribute to be a new instance of the MediaTransportControls class – this is actually what the default behaviour does; the difference is that I now have access to an instance that I can set attributes on. Here I’m enabling, and showing both the buttons to skip forward/backward and the buttons for fast forward/rewind. The updated layout looks like the following:

image

As you can see from the image the skip forward and backward buttons default to 30 and 10 seconds respectively. In order to adjust these you’ll need to override the behaviour that is associated with the skip forward/backward buttons, which can be done by attaching an event handler to the PositionReceived event on the MediaPlaybackCommandManager:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
     base.OnNavigatedTo(e);

    Player.MediaPlayer.CommandManager.PositionReceived += CommandManager_PositionReceived;
}

private void CommandManager_PositionReceived(MediaPlaybackCommandManager sender, MediaPlaybackCommandManagerPositionReceivedEventArgs args)
{
     sender.MediaPlayer.PlaybackSession.Position = TimeSpan.FromMinutes(2);
     args.Handled = true;
}

In this case, I’ve named the MediaPlayerElement in the XAML (ie by adding x:Name=”Player” to the MediaPlayerElement), and then when the page has been navigated to I’m attaching the appropriate event handler. When either skip forward or backward is pressed, the position in the playback is set to the 2 minute mark and the args.Handled property is set to true, effectivey overriding the default skip behaviour. Big reminder: if you are attaching event handlers in code, make sure you detach them too (ie PositionReceived –= CommandManager_PositionReceived in the OnNavigatedFrom method).

The fast forward and fast rewind buttons will increment the playback speed up and down by doubling the rate over the range of rates supported by the content (eg –8, –4, –2, –1, 1, 2, 4, 8). The MediaTransportControls class is clever enough to detect the supported range of rates and automatically disable the fast foward/rewind buttons when the limit on the range has been reached.

Note: In working with the MediaPlayerElement, and even in preparing the sample code for this blog post, I was not able to get the fast rewind functionality to work. Fast foward appears to work but it causes the control bar to hide and show in a weird oscillating fashion. My recommendation would be to give these buttons a wide birth as this feature is severely under baked – if you want to implement something similar, perhaps with thumbnails, you should consider implementing it yourself!!! (and yes, we’ve had to do this on a project)

In this post, you’ve seen the basics of adding a MediaPlayerElment and playing some content using the built in media controls. I’ll go into more detail soon on really customising the style of your player.

Update: It seems that by setting the minimum version of the UWP application to the Fall Creators update, it appears that fast forward/rewind seems to work. I’m guessing it may have been fixed!

View Model States and Connecting them to Xamarin Forms Visual States using BuildIt

In my previous post on Getting Started with Visual States in Xamarin Forms using BuildIt.Forms I showed a very basic example of defining and triggering Visual States within a Xamarin Forms application. However, most applications have more complexity where each page is typically data bound to a corresponding ViewModel and it is the ViewModel which encapsulated the logic of the application.

Let me walk through working with a ViewModel using the same basic example I started in my previous post. In this case I’m going to add another panel to the page which will be displayed after the user clicks the Login button, effectively simulating the experience of showing a progress indicator whilst the application is authenticating the user.

<!-- Authenticating Prompt -->
<Grid BackgroundColor="LightPink"
         x:Name="AuthenticatingIndicator"
         IsVisible="false">
     <Label Text="Attempting to authenticate you..."
             HorizontalTextAlignment="Center"
             VerticalOptions="Center" />
</Grid>
<!-- END Authenticating Prompt –>

In this case I’m going to add a new VisualStateGroup to define the visual states to hide and show the AuthenticatingIndicator Grid.

<vsm:VisualStateGroup Name="AuthenticationStates">
     <vsm:VisualState Name="Authenticating">
         <vsm:VisualState.Setters>
             <vsm:Setter Element="{x:Reference AuthenticatingIndicator}"
                         Property="IsVisible"
                         Value="true" />
         </vsm:VisualState.Setters>
     </vsm:VisualState>
     <vsm:VisualState Name="NotAuthenticating" />
</vsm:VisualStateGroup>

A VisualStateGroup is designed to hold mutually exclusive states. A page can have any number of VisualStateGroups, and at any given point in time the current state of the page can consist of being in one VisualState from each group. In this scenario we have broken the authenticating states away from the loading states because in theory you might want to disply both the AuthenticatingIndicator, as well as the LoadingIndicator.

The last piece of XAML that I need to update is to attach an event handler to the Clicked event of the Button:

<Button Text="Login"
         Clicked="LoginPressed" />

And in the code behind, define the corresponding LoginPressed method (and yes, those MVVM purist will argue that this would be better using the Command property through to the ViewModel but we’ll leave that for another post):

protected async void LoginPressed(object sender, EventArgs e)
{
}

Now that we have the XAML defined, it’s time to look at how we can drive this from our ViewModel. In my case the page I’m working with is called MainPage.xaml, so I’m going to define a class called MainViewModel in a separate .NET Standard library. I’m not going to add a reference to BuildIt.Forms to the .NET Standard library because that would bring in a reference to Xamarin Forms, which should not be referenced by the library that holds your ViewModels – they should be abstracted away from any concrete interface, which includes Xamarin Forms, even though it is itself an abstraction from the native platform interfaces. What I am going to reference is the BuildIt.States library, which is a .NET Standard library that has no reference to any specific user interface framework, making it perfect for managing states within your ViewModel.

Alongside the MainViewModel class I’m also going to define an enumeration where the names match the corresponding visual states: the enum type name has to match the VisualStateGroup name and the enum values have to match the VisualState name.

public enum AuthenticationStates
{
     Base,
     Authenticating,
     NotAuthenticating
}

The enum also has an additional value, Base, which is will be the default enum value. The name of this value is irrelevant but it’s important to have it as the first value and should not correspond to any VisualState name.

The MainViewModel class includes a StateManager property. In this case the constructor calls the extension method DefineAllStates to define states for each value of the AuthenticationState enum. The BuildIt States library has a host of great features that are worth explaining but I’ll save that topic for another post. The important thing is that each of the states for the AuthenticationState enum are defined.

public class MainViewModel
{
     public IStateManager StateManager { get; } = new StateManager();

    public MainViewModel()
     {
         StateManager.Group<AuthenticationStates>().DefineAllStates();
     }

    public async Task Login()
     {
         await StateManager.GoToState(AuthenticationStates.Authenticating);

        await Task.Delay(2000);

        await StateManager.GoToState(AuthenticationStates.NotAuthenticating);
     }
}

The Login method simply calls the GoToState method prior to calling Task.Delay, to simulate attempting to authenticate the user, and then again calling GoToState to change the state back to the NotAuthenticating state.

Now that we have our MainViewModel defined, I need to connect it to my MainPage. For real applications we work on at Built to Roam, we use frameworks such as MvvmCross to connect the View and ViewModels. However, for brevity I’m going to simply create an instance of the MainViewModel as part of the MainPage:

private MainViewModel ViewModel { get; } = new MainViewModel();

And then set the instance as the BindingContext of the page, in the constructor:

public MainPage()
{
     InitializeComponent();

    BindingContext = ViewModel;
}

Lastly, I’ll update the LoginPressed method to call the method on the MainViewModel:

protected async void LoginPressed(object sender, EventArgs e)
{
     await ViewModel.Login();
}

At this point we’re almost done: We have a ViewModel that defines the states of the application in a way that they can be tested in absence of any user interface implementation, and the View (in this case the MainPage) will invoke the Login method to trigger the state changes. The only missing component is connecting the Visual States defined on the MainPage XAML, with the states defined in the MainViewModel. This is done using the Bind method within the OnAppearing override:

await VisualStateManager.Bind(this, ViewModel.StateManager);

Now I’m ready to go – at this point the user experience is entirely defined in XAML, with all my logic, including the states, encapsulated within my ViewModel, ready to be tested.

Getting Started with Visual States in Xamarin Forms using BuildIt.Forms

Over the past couple of months we’ve been working on getting the BuildIt.Forms library to a point where it was stable enough to promote and talk about. With the recent release of the 2.4 update for Xamarin Forms, we’re finally able to push out a stable release.

The BuildIt.Forms library brings with it quite a few features but probably the best reason to use the library is the support it adds for defining Visual States within your Xamarin Forms application within the XAML, just like you would if you were building using XAML for UWP (or any other XAML platform such as WPF etc). We’ve tried to stay as true as possible to the syntax for Visual States used on other platforms but like all things Xamarin Forms there are some differences that you’ll need to get your head around.

Ok, before we jump in, let’s take a back step and look at what a Visual State really is, and why you’d want to use them. Let’s start with a very simple example – imagine you have a page within your application that needs to load some data and you want to provide a visual cue that something is happening. In this case I’m going to add a simple overlay with some text indicating that information is being loaded:

<!-- Loading Prompt -->
<Grid BackgroundColor="LightGray"
         x:Name="LoadingIndicator"
         IsVisible="false">
     <Label Text="Loading..."
             HorizontalTextAlignment="Center"
             VerticalOptions="Center" />
</Grid>
<!-- END Loading Prompt –>

Note that the default IsVisible value is false, meaning that the LoadingIndicator Grid will not be visible. In the codebehind of the page I can then add code that would show the LoadingIndicator Grid, simulate loading content (ie Task.Delay), and then hide the LoadingIndicator Grid.

protected override async void OnAppearing()
{
     base.OnAppearing();

    LoadingIndicator.IsVisible = true;

    await Task.Delay(2000);

    LoadingIndicator.IsVisible = false;
}

Of course in a real application you wouldn’t do this, as there should be at least a ViewModel that would do the loading but we’ll come back to the use of ViewModels later. For the moment, it’s enough to point out that we controlling the appearance of individual elements based on the state of the page (ie showing the LoadingIndicator when the page is in the loading state). What would be great is if we could declare these states in XAML, which is where the BuildIt Forms library comes in.

I’ll add a few namespaces to the XAML for the page (mainly so I don’t forget to add them later when we talk about animations and other controls in the BuildIt Forms library):

xmlns:ctrl="clr-namespace:BuildIt.Forms.Controls;assembly=BuildIt.Forms.Controls"
xmlns:vsm="clr-namespace:BuildIt.Forms;assembly=BuildIt.Forms.Core"
xmlns:anim="clr-namespace:BuildIt.Forms.Animations;assembly=BuildIt.Forms.Core"

Next, immediately inside the root tag of the page, I’ll define two visual states:

<vsm:VisualStateManager.VisualStateGroups>
     <vsm:VisualStateGroups>
         <vsm:VisualStateGroup Name="LoadingStates">
             <vsm:VisualState Name="Loading">
                 <vsm:VisualState.Setters>
                     <vsm:Setter Element="{x:Reference LoadingIndicator}"
                                 Property="IsVisible"
                                 Value="true" />

                 </vsm:VisualState.Setters>
             </vsm:VisualState>
             <vsm:VisualState Name="Loaded" />
         </vsm:VisualStateGroup>
     </vsm:VisualStateGroups>
</vsm:VisualStateManager.VisualStateGroups>

The important things to note are the names of the states: Loading and Loaded, and the use of a Setter element to adjust the IsVisible property on the LoadingIndicator element. Note that I didn’t need to set the IsVisible property to false in the Loaded state – this is because the default value of the IsVisible property on the LoadingIndicator is set to false, and the Visual State manager is clever enough to remember that when switching between states.

Now that we have visual states defined, let’s switch to the code behind and adjust the code to use the visual states:

protected override async void OnAppearing()
{
     base.OnAppearing();
    await VisualStateManager.GoToState(this, "Loading");
    await Task.Delay(2000);
     await VisualStateManager.GoToState(this, "Loaded");
}

It looks like we haven’t made any great improvements but here’s where the power is – let’s add some content to the screen that will be shown when the loading is complete:

<!-- Login Prompt -->
<Grid x:Name="LoginPrompt"
         IsVisible="False">
     <StackLayout>
         <Label Text="Username:" />
         <Editor />
         <Label Text="Password:" />
         <Editor />
         <Button Text="Login" />
     </StackLayout>
</Grid>
<!-- END Login Prompt –>

In the past, this would have required more code in the code behind to adjust the IsVisible property on the LoginPrompt Grid in order to show the content. With visual states, there is no need to alter the logic of the application, I just need to adjust the Loaded visual state by adding a Setter to set the IsVisible property to true.

<vsm:VisualState Name="Loaded">
     <vsm:VisualState.Setters>
         <vsm:Setter Element="{x:Reference LoginPrompt}"
                     Property="IsVisible"
                     Value="true" />

     </vsm:VisualState.Setters>
</vsm:VisualState>

At the moment I have built an interface that provides useful feedback to the user about the loading state of the application. However, there is a rather abrupt change between the LoadingIndicator Grid and the LoginPrompt. It would be nice to be able to add animations to make the transition smoother. Again without adjusting the logic of the application I can do this by adding animations directly to the visual states. The following animation can be added after the Setters of the Loading state.

<vsm:VisualState.LeavingAnimations>
     <anim:AnimationGroup>
         <anim:AnimationGroup.PreAnimations>
             <anim:FadeAnimation Duration="500"
                                 Opacity="0"
                                 Element="{x:Reference LoadingIndicator}" />
         </anim:AnimationGroup.PreAnimations>
     </anim:AnimationGroup>
</vsm:VisualState.LeavingAnimations>

In this case the animation will be run prior to (ie a PreAnimation) any state change away from (ie a LeavingAnimation) the Loading state, and will fade the LoadingIndicator Grid out to 0 Opacity over a duration of 500 milliseconds.

In this post I’ve covered the basics of creating Visual States. In my next post I’ll cover using states in a ViewModel and how you can link them to the Visual States on the page to give you a more testable application.

Hey, who moved my… Visual Studio Emulator for Android?

A while ago, in response to a common frustration from Xamarin developers, Microsoft released the Visual Studio Emulator for Android and it even made it into the Visual Studio installer:

image

As a long-serving Windows Phone developer I embraced this decision as the emulator was based on Hyper-V which meant that it played nicely with the Windows Phone emulators – I could now do cross platform development, even when I didn’t have real devices with me. Unfortunately, Microsoft have indicated that the emulator is no longer going to receive updates, so anyone wanting to dev/test on more recent builds of Android are out of luck. This was really frustrating as the emulator was both quick (relative to the out of the box emulators from Google – historically) and didn’t require another emulator sub-system (as it worked on Hyper-V).

Recently, Microsoft have actively discounted Windows Phone, making it very hard to justify any developer resources on building for Windows Phone…. it also makes me question the value proposition of UWP over WPF, but that’s a topic for a different post. The upshot is that there is no longer a reason for me to have the Windows 10 Mobile emulators installed, which means I have no need for Hyper-V, which means I can use any one of the great Android emulators out there that don’t play nice wiht Hyper-V.

What’s really cool is that Microsoft have included the Google Android Emulator in the Visual Studio installer. You need to make sure that both the Google Android Emulator and the Intel Hardware Accelerated Execution Manager are installed.

image

After installing the Google emulator you can launch your application on the emulator the same way you would to a real device – it appears in the devices dropdown. You can also access the different emulator images via the Android Emulator Manager.

image

Whilst the Android Emulator Manager is not a great looking dialog, it does allow you to customise and launch the different emulators.

image

I was so surprised when I launched the updated emulator. I was expecting an old, slow, crappy looking emulator but was surprised with an updated emulator shell with all the features that I’d come to expect from an emulator.

image

I’m a convert – Whilst I’ll still use a real device for most development work, having a good emulator is critical for those times when I don’t have a device with me. Cudos to Microsoft for firstly pushing Google to build a better developer experience and secondly making the Visual Studio installer so simple to install the emulator.

Sidenote: I did have to update one component from the Android SDK. Make sure you read the build output window in Visual Studio if you are running into issues as it pointed me to an out of date component.

Visual Studio or Blend Exception When Using XAML Designer

Today we ran into a nasty issue with the XAML design experience in Visual Studio and/or Blend throwing an exception:

image

Exceptions in the designer a quite often a result of code being run by the designer that is insufficiently protected using try-catch, or has assumptions that some app startup code has run, resulting in an exception that bubbles up and causes the designer to fail. For these exceptions, I recommend checking out the post How to Debug the XAML Designer by Travis Illig, which uses another instance of Visual Studio to debug and hopefully identify the code that isn’t playing nice.

Unfortunately in our case, this didn’t help because Visual Studio (and same in Blend) was failing to resolve an assembly reference.

image

One thing that Travis point out is that there is a ShadowCache folder located at C:\Users\yourusername\AppData\Local\Microsoft\VisualStudio\15.0_317bf9c1\Designer\ShadowCache (note that you’ll need to change both “yourusername” to be your username and perhaps even the 15.0…. to reflect the current version of Visual Studio. Change VisualStudio to Blend if you’re using Blend). Within the ShadowCache folder there will be folders created for each application where you use the designer, and then a series of “bin” sub folders that will contain assemblies referenced by your application.

image

The issue we found was that we were referencing a nuget package that includes both a UWP dll as well as a .NET Standard dll. Whilst the UWP dll was being copied into a bin folder, the .NET Standard dll was not. Our fix for getting the designer to work was to copy the .NET standard dll into the same folder as the UWP dll.

Unfortunately whilst this gets the designer to work, it is a sub-optimal experience as it appears that it needs to be done every time Visual Studio is run, or when the designer process is restarted.

Getting Started: Xamarin Forms with .NET Standard 2.0

In my earlier post Getting Started: Xamarin Forms with .NET Standard I covered how to create a new Xamarin Forms project which uses a .NET Standard 1.4 library to share the views between iOS, Android and UWP. At the time, whilst iOS and Android supported .NET Standard 2.0, support still wasn’t available for UWP. Almost immediately after publishing the blog post, Microsoft announced that Visual Studio 2017 preview 15.4 would allow UWP applications to reference .NET Standard 2.0 libraries. Unfortunately this didn’t work in the first drop, 15.4.0 Preview. This was just updated to 15.4.0 Preview 2 (Release Notes: https://www.visualstudio.com/en-us/news/releasenotes/vs2017-preview-relnotes), which brings with it the support we’ve been after. In this post, I’m going to repeat the previous post on getting started with .NET Standard, this time using .NET Standard 2.0 for the UI project.

Let’s walk through the basics – create a new Cross Platform App (same as before)

image

Select the Xamarin.Forms (UI Technology) and Portable Class Library (PCL) (Code Sharing Strategy) – Don’t pick the Shared Project option!

image

Select the Insider Preview version of UWP for both Minimum and Target version – this is required for .NET Standard 2.0 support. If you want to target earlier versions of Windows 10, you’ll have to stick with .NET Standard 1.4.

image

Next, we’re going to replace the PCL with a new .NET Standard library

image

I’ll copy the App.xaml, App.xaml.cs, MainPage.xaml and MainPage.xaml.cs from the PCL into the .NET Standard library, before deleting the PCL from the project (see https://nicksnettravels.builttoroam.com/post/2017/08/26/Getting-Started-Xamarin-Forms-with-NET-Standard.aspx for more detailed instructions).

The big difference is that I’m not going to change the default Target Framework, leaving it as .NET Standard 2.0.

image

Next I need to make sure I add and upgrade references to Xamarin.Forms to each of the projects – this isn’t actually required, since the stable release of Xamarin Forms will actually work with .NET Standard but I’ve been working with the pre-release version quite a bit lately, so I’ll go with that for this example.

image

I also need to remember to add a reference to the .NET Standard project to each of the head projects for iOS, Android and UWP.

image

If you attempt to build and run at this point iOS and Android should work without issue. UWP will most likely compile but will raise an exception “Could not load file or assembly ‘netstandard, Version=2.0.0.0….” at runtime.

image

Essentially the UWP project structure has evolved a little, so you need to upgrade it. Now I think that you may be able to do this via package manager but I’ve never got it to work for UWP projects, so I will make the changes manually to the csproj file. Start by deleting the project.json file from the UWP project.

Next right-click the UWP project in Solution Explorer and select unload project. Next, right-click on the UWP project node and select Edit MySecondXamarinFormsApp.UWP.csproj.

Add a new PropertyGroup – this changes the way packages are referenced, eliminating the need for the project.json file, replacing it with references within the csproj file.

<PropertyGroup>
   <RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>

image

Next we need to add back the package references that were in the project.json – if you’re doing this on an existing project, you may want to keep the project.json file handy so you know which packages to add. In this case there are just two projects:

<ItemGroup>
   <PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
     <Version>6.0.0-preview1-25631-01</Version>
   </PackageReference>
   <PackageReference Include="Xamarin.Forms">
     <Version>2.4.0.269-pre2</Version>
   </PackageReference>
</ItemGroup>

image

Now you can right-click on the UWP project in Solution Explorer and select Reload project. Trigger a rebuild and now you should be able to run the UWP project.

image

Source Code Debugging with BuildIt Libraries

I was working on the BuildIt libraries yesterday and got slightly distracted – I was looking for how to make a small change to the way the Nuget packages are generated and ended up investing time in getting symbol source server support added. At first I thought “this is going to be easy and so awesome” but this quickly turned into frustration as it just didn’t seem to work. Turns out that whilst I was able to successfully generate the nuget symbol package locally, what I’d forgotten is that because we separate our build and release process (done via Visual Studio Team Services), I needed to make sure all my source code files are added to the build artefacts. The nuget packages are generated as part of our release process, which includes generating the symbol package which needed to include the source code files.

The upshot is that I’ve got source code debugging added to both BuildIt.General and BuildIt.States, with other packages to get it as we roll out stable builds in the coming weeks.

To get source code debugging to work, the first step is to configure Visual Studio to use the symbolsource server when attempting to step through source code. I followed the instructions at http://www.symbolsource.org/Public/Home/VisualStudio, which I’ve repeated here with the exact setup I used:

In Visual Studio:

  • Go to Tools -> Options -> Debugger -> General.
    • Uncheck “Enable Just My Code (Managed only)”.
    • Uncheck “Enable .NET Framework source stepping”.
    • Check “Enable source server support”.
    • Uncheck “Require source files to exactly match the original version”

image

image


With this all setup, you’ll find that the next time you run your application it will be incredibly slow to start debugging as it has to go through and look up the symbols for each library you have references. However, when you do finally get your application up and running you’ll be able to step through and see more information about what’s going wrong with third party libraries that have symbol and source code support.

For the BuildIt libraries (General and States) the only additional step is to update to the latest stable release (1.1.0.75 at time of writing). Run the application, and you can now step through on calls made to functions contained within these libraries. You’ll also be able to intercept any exceptions that are raised within the libraries.

image

Happy Debugging!

Getting Started: Xamarin Forms with .NET Standard

With the recent release of Visual Studio 2017 v15.3 (and subsequent patch release 15.3.1 and 15.3.2…. yes, it does say something about ship quality Sad smile) came the release and support for .NET Standard 2.0. The Xamarin team also made a lot of noise about support for .NET Standard 2.0; unfortunately this doesn’t yet translate into Visual Studio templates that easily get you started. My particular annoyance is the about of steps you need to go through in order to just spin up a new Xamarin Forms application that can reference .NET Standard libraries. I thought I’d piggyback of a post done a couple of months back by Pierce Boggan. Here goes:

Start by creating a new project in Visual Studio 2017, selecting the Cross Platform App (Xamarin) project template:

image

Next, select the template you want (I’m going with the Blank App), the UI Technology and Code Sharing Strategy. As I’m going to be walking through how to use Xamarin Forms, it makes sense to pick that as the option for UI Technology. Only select the Portable Class Library option. Don’t use the Shared Project – using a shared project will lead you down the evil road of using conditional compilation which will be a maintenance nightmare, just don’t use it. I don’t care how great you think it is, don’t use it. One last time, don’t use the Shared Project option.

image

Now that I’ve expressed my opinion on code sharing strategies, let’s click the OK button and get on with building our application. As the template goes through generating the head projects for iOS, Android and UWP, it will prompt you to select the target and minimum platforms for UWP. For the most part, unless you have specific target platform requirements for UWP, you can leave the default settings.

image

The generated solution will have four projects: three head or target platform projects (for iOS, Android and UWP) and a portable class library (PCL) which contains the XAML pages that will make up your Xamarin Forms application layout. In order to proceed with .NET Standard support we need to replace the PCL with a .NET Standard library. Whilst Visual Studio used to have a mechanism for upgrading a library from a PCL to a .NET Standard library, this has been removed. Now the easiest way is to simply create a new project, and copy the relevant files into the new project. From the Add New Project dialog, select the Class Library (.NET Standard) template.

image

I use the .UI naming convention for the library that will contain my XAML pages. Other developers use .Core but my preference is to separate my XAML pages away from my view models. Whilst technically with Xamarin Forms they can reside in the same library, I prefer to have a clean separation between them. I have <applicationname>.UI with my XAML pages in it and <applicationname>.Core with my view models, services, entities, essentially all the business logic for my application.

For this example I’m going to keep it simple and we’ll just create the .UI project for the moment.

image

I don’t need the default Class1.cs, so I’ll remove that. I’ll add a reference to the .NET Standard library to all the head projects.

I’m also going to drop the .NET Standard version back from 2.0 (now the default in Visual Studio) back to 1.4. Whilst the tooling has been updated for the head projects for iOS and Android to support .NET Standard 2.0, of course, UWP is still lagging the field, as so you won’t be able to use a .NET Standard 2.0 library until that’s fixed. To be honest though, not much is lost by lowering the version of the .UI project to 1.4 since all the features of Xamarin Forms are still there.

image

Next I’m going to copy App.xaml (and App.xaml.cs) and MainPage.xaml (and MainPage.xaml.cs) from the PCL into the newly created .NET Standard library. Once I’ve copied these files across I can remove the PCL project from the solution – this will remove the references to this library from each of the head projects. After coping these files across, you may well see a compilation error similar to the following:

1>------ Build started: Project: MyFirstXamarinFormsApp.UI, Configuration: Debug Any CPU ------
1>C:\Program Files\dotnet\sdk\2.0.0\Sdks\Microsoft.NET.Sdk\build\Microsoft.NET.Sdk.DefaultItems.targets(274,5): error : Duplicate 'EmbeddedResource' items were included. The .NET SDK includes 'EmbeddedResource' items from your project directory by default. You can either remove these items from your project file, or set the 'EnableDefaultEmbeddedResourceItems' property to 'false' if you want to explicitly include them in your project file. For more information, see
https://aka.ms/sdkimplicititems. The duplicate items were: 'App.xaml'; 'MainPage.xaml'
1>Done building project "MyFirstXamarinFormsApp.UI.csproj" -- FAILED.

If you do, you just need to edit the project file for the .UI project and remove the App.Xaml and MainPage.xaml EmbeddedResource elements. The new project format includes files by default and the tooling isn’t smart enough to realise that the sample files are being added multiple times. Removing these elements will fix the compilation:

<ItemGroup>
   <EmbeddedResource Include="App.xaml">
     <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
   </EmbeddedResource>
   <EmbeddedResource Include="MainPage.xaml">
     <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
   </EmbeddedResource>
</ItemGroup>

The last thing to do is to make sure that the .NET Standard library references Xamarin Forms. I’m going to do that by right-clicking the solution node in Solution Explorer and selecting Manage Nuget Package for Solution.

image

I’m going to select the new prerelease version of Xamarin Forms (which is the one where they’ve apparently added .NET Standard support). In addition to adding a reference to Xamarin Forms to the UI project, I also take this opportunity to upgrade all the package references in the application. Note that I’ve even selected the Android support packages – this used to be a big No-No but with the latest version of the tooling you can now go ahead and update them, and I would definitely encourage you to do so.

image

Now, go make yourself a coffee – Nuget is slow, so slow! The good news is that once you’ve done all these steps, you’re ready to go with a .NET Standard based Xamarin Forms project. If you’re following this post to get started on your own project, you can finish up here, as you’re good to go.

Ok, so all of that, and what can we do. We’ll for a starters, it makes it super easy to add nuget packages such as BuildIt Forms which has a bunch of helper controls and features to get you building richer applications. Let’s add a reference to the BuildIt.Forms Nuget package the project:

image

After adding the reference to BuildIt.Forms we can make use the added controls. For example the ContentButton allows us to easily add a button that contains any XAML content, whilst still maintaining the pressed and hover states:

<?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:local="clr-namespace:MyFirstXamarinFormsApp"
              xmlns:ctrls="clr-namespace:BuildIt.Forms.Controls;assembly=BuildIt.Forms.Controls"
              x:Class="MyFirstXamarinFormsApp.MainPage">
 
     <StackLayout VerticalOptions="Center"
                  HorizontalOptions="Center">
         <Label Text="Welcome to Xamarin Forms!" />
         <ctrls:ContentButton>
             <Label Text="Press m!" />
         </ctrls:ContentButton>
     </StackLayout>
</ContentPage>

I’ll cover more on the BuildIt.Forms library in coming posts.