Handling and intercepting Back button Navigation in Xamarin Forms Shell

I’ve recently ended up needing to ask if the user really wants to navigate away from a page in my Xamarin app, Net Writer. Essentially whilst a post is being edited I don’t want the user to accidentally lose their progress, necessitating the need to inject a “Are you sure?” or “Confirm exit” prompt when the user presses either the Android hardware or OS level back button or the back button on the navigation bar provided by the Xamarin Forms Shell.

I found a blog post by Bohdan Benetskyi from March 2020, but it was geared for MvvmCross and not Xamarin Forms Shell. Here is how to adapt it.

Introducing IBackButtonHandler to your Page

If you have existing pages you can add an interface to them and implement it, for example here is a page from my app with IBackButtonHandler added to the class:

  [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class PostListSummaryPage : ReactiveContentPage<PostSummaryListPageViewModel>, IBackButtonHandler
    {

This can then be implemented however you like, returning true if the back navigation should be aborted, for example:

public async Task<bool> HandleBackButton()
{
    if (await ShouldNotGoBack())
    {
        return true;
    }

    return false;
}

public async Task<bool> ShouldNotGoBack()
{
    var response = await this.DisplayActionSheet("Would you like to discard any unsaved changes to this post?", "No", "Yes, go back");

    return response == "No";
}

Once that is done next up is wiring up the back buttons.

Handling the Android OS back button

To handle the OS level back button you’ll need to add the following to MainActivity.cs:

public async override void OnBackPressed()
{
    var backButtonHandler = Shell.Current.CurrentPage as IBackButtonHandler;

    if (backButtonHandler == null)
    {
        base.OnBackPressed();
        return;
    }

    var backButtonHandled = await backButtonHandler.HandleBackButton();
    if (!backButtonHandled)
    {
        base.OnBackPressed();
    }
}

Lets step through this. First up, it attempts to cast the current Shell page as IBackButtonHandler. This means that only Pages that implement this interface will have any change of behaviour here. If the interface is not implemented, the base implementation of OnBackPressed() is called. If it is implemented, the HandleBackButton method is evaluated. If it returns true, the back navigation is cancelled. If false, the base implementation of OnBackPressed() is called, continuing the back navigation.

Handling the Shell back button

This is the button on the top left that shows when you are more than one level deep in the navigation stack. Handling this is less clean as it requires adding a call to Shell.SetBackButtonBehaviour in the constructor of each page that requires this. For example, add the following to the constructor of your page, after InitializeComponent():

Shell.SetBackButtonBehavior(this, new BackButtonBehavior()
{
    Command = new Command(async () => {

        var backButtonHandled = await this.HandleBackButton();
        if (!backButtonHandled)
        {
            await Navigation.PopAsync();
        }

    })
});

After that, you’l get a nice prompt pop up whenever you hit the OS back button or the shell navigation back button, but only on pages that implement IBackButtonHandler.

Walkthough video

If you would like a video walkthough of the above, check out this video:

How to confirm Xamarin Forms Shell Navigation Back Button
Watch this video on YouTube.

Adding an Admin Panel to a .NET Core web app with CoreAdmin

I’ve published version 1.0.0 of a new open source package and a corresponding nuget package – CoreAdmin.

CoreAdmin adds a nice set of CRUD screens to your .NET Core web app in one line of code!

Adding CoreAdmin to your app

Given a typical Startup.cs file, you will have a ConfigureServices method. You need to add the line services.AddCoreAdmin() somewhere near the bottom (at least after you register your Entity Framework DbContexts).

Then when you visit your site with /coreadmin on the end of the URL, you’ll see this:

On the left you can see your database tables (these are the DBSets in your DbContexts). Click one and you get:

From here you can Create new entities, Delete and Edit them. Full searching, sorting, filtering etc are also supported.

There are a few limitations on data types and primary keys (for example, entities with composite primary keys are not supported for editing or deletion yet) but this should be sufficient for basic quick and dirty editing of entities.

How to get it

CoreAdmin on Github

CoreAdmin on NuGet

Simply install the nuget package “CoreAdmin” and you are good to go!  

Or watch a demo!

Here is a YouTube Style video demo.

Add An Admin Panel to a .NET Core App in 2 Minutes!
Watch this video on YouTube.

Multiple monitors? You should buy VMWare Fusion instead of Parallels Desktop

In a post three years ago, I waxed lyrical about how much better Parallels Desktop was compared to VMWare for the very common task of running Windows on your Mac.

It’s time to take that back.

Parallels Desktop is no longer fit for purpose if you are an advanced user.

How Parallels Desktop broke multiple monitors

In older versions of macOS, virtual desktops spanned your whole set of monitors. Therefore if you had a left and right monitor, switching spaces (or virtual desktops) would switch both, giving you two “Desktops”, Desktop 1 (left monitor A and right monitor A) and “Desktop 2”, (left monitor B and right monitor B). Switching between desktops would switch both screens. The major downside of this was that when applications were run “Full screen” (rather than just maximised), they would go full screen on one monitor and leave the other one completely blank, which was complete madness

In Parallels 11, Parallels supported two ways of rendering full screen on multiple monitors. The first was using macOS’s built in full screen function (more on that in a minute) and the other using a “non-native” method that involved drawing a windowless fullscreen window on top of the whole screen. 

To work around the full screen issue when using multiple monitors, macOS Yosemite introduced the option for displays to have their own “Spaces”. This meant that your left and right monitors have their own sets of virtual desktops. However, this meant that each monitor could be switched desktop independently, introducing say 4 different combinations when you had two monitors and two desktops. This was a context switching nightmare. Most power users turn this off, especially if they are using keyboard shortcuts (CTRL+arrow keys) to switch between spaces because the monitor that would switch would be the one your mouse cursor was over.

The combination of turning off “Displays have separate Spaces” in macOS, and disabling “native full screen mode” in Parallels was the perfect, wanted behaviour that Parallels users of multiple monitors had become accustomed to for many, many years.

Parallels 12 changed all that, by removing the non-native full screen mode option that was working perfectly in version 11, leaving users with no satisfactory multi-monitor display mode.

Users were up in arms:

8 pages of complaints on the official Parallels forum when Parallels 12 launched with this

“Usable” multi-monitor support feature request

Did Parallels listen? Well, only a little. Near the end of version 12’s shelf life they pushed an update out that contained a work around – an option to “switch” all other spaces to Parallels when you clicked Parallels on another space. Sounds great but still doesn’t allow you to switch in and out of Windows on all of your screens at once.

Users were livid. The pithy Knowledge Base article didn’t help either.

Then Parallels 13 came out with no new fixes for this. Parallels was effectively dead for users with multiple monitors.

Other reasons not to use Parallels any more

The push for yearly subscription pricing. You aren’t Creative Cloud guys. The last thing users want when buying a piece of utility software is to set calendar reminders that they are going to be auto-rebilled.

The shovelware and crapware that Parallels pushes on you, even via advertisements with the application that you paid for. Who doesn’t want a subscription to Parallels Remote Access or “Parallels Toolbox”?

Only 9.99 USD a year!!

The resurrection of VMWare Fusion

Back in the day, Parallels spanked VMWare Fusion on performance. They became market leaders and deserved it. I fondly remember running Parallels 4 against a Bootcamp partition on a now clunky old Mac Mini and being pleasantly surprised.

I’ve recently given VMWare Fusion 8.5 a go and I am pleased to say the performance against Parallels for my main use case (Visual Studio on Windows 10) is indistinguishable. It imported my Parallels VM flawlessly. It didn’t pester me to install anti-virus in my Windows 10 VM (something so completely pointless Parallels must be getting kickbacks). There will be a free upgrade to VMWare Fusion 10 this October. And most importantly…

It works correctly with multiple monitors!

Yes, VMWare Fusion 8.5 behaves the same way Parallels 11 used to work.

RIP Parallels Desktop.