Xamarin – Display a loading graphic when performing an async operation

Still learning Xamarin. I have built a login page, validation, called a web api to login and stored credentials after the user has logged in. I now wanted to show a loading graphic whilst the web api is being hit.

Xamarin has a built in control called ActivityIndicator.

I defined a new property in my ViewModel to determine when to show the ActivityIndicator

bool isBusy = false;
public bool IsBusy
     get { return isBusy; }
     set { SetProperty(ref isBusy, value); }

Without going too far off topic, this property was already included in my project by Visual Studio in a BaseViewModel. The call to SetProperty(ref isBusy, value); looks to be there to only raise OnPropertyChanged if the property has actually changed. So it could have been replaced with isBusy = value; OnPropertyChanged(nameof(IsBusy));

Then when we hit the API

IsBusy = true;
var userId = await ApiLogin();
IsBusy = false;

We can now show the ActivityIndicator when this is true. But for the form, which is shown when the ActivityIndicator isn’t, setting a binding like {Binding !IsBusy} does not work, nor does {Binding IsBusy.Equals(false)}
To do this I used a ValueConverter

    public class InverseBoolConverter : IValueConverter
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            if (!(value is bool))
                throw new InvalidOperationException("The target must be a boolean");

            return !(bool)value;

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            return !(bool)value;

To use this in the view I had to add an xmlns – xmlns:converters=”clr-namespace:VCReportMobile.Converters”
And add a reference to the converter in the ResourceDictionary

            <converters:InverseBoolConverter x:Key="inverter"/>

This is then referenced like IsVisible=”{Binding IsBusy, Converter={StaticResource inverter}}”

        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    <StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="Fill">
        <StackLayout Orientation="Horizontal" HorizontalOptions="Center" VerticalOptions="Center">
            <ContentView Padding="0,30,0,25" VerticalOptions="FillAndExpand">
                <Image Source="Logo.png" VerticalOptions="Center" HeightRequest="75" />

    <ActivityIndicator Color="Black" IsRunning="{Binding IsBusy}" IsVisible="{Binding IsBusy}" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand" Grid.Row="1" />

       <ScrollView Grid.Row="1" IsVisible="{Binding IsBusy, Converter={StaticResource inverter}}">
<!-- the login form, etc -->

The ActivityIndicator and the ScrollView both have Grid.Row=”1″, but since only one is visible at any time then it works.


If you need to use the InverseBoolConverter  on more than 1 page, then it can be placed in the App.xaml (along with it’s xmlns)

Leave a Reply

Your email address will not be published. Required fields are marked *