Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Triggering Activity Indicator in Xamarin Forms

Tags:

c#

xaml

xamarin

I have an icon on my Xamarin.Forms app, which when it is clicked, I would like to change it to an activity indicator. It looks as though I should use a Trigger, Event Triggers look good, but as my image is declared in XAML, I am not sure quite how it would fit together?

At the moment, I have this in XAML at the bottom of a stacklayout:

<Button x:Name="NewDeviceButton" 
          Image="glyphish_31_circle_x.png" 
          HorizontalOptions="End"
          VerticalOptions="EndAndExpand" />

When it is clicked, I would like to show this, for a set amount of time, then trigger some C# functionality:

<ActivityIndicator Color="Black" IsRunning="true" />

I am not sure whether it would be best to configure it all in XAML with a trigger, or if i can just have a placeholder type item in XAML and then have all the definitions in C#?

like image 868
George Edwards Avatar asked Sep 01 '15 14:09

George Edwards


2 Answers

There are a few ways of doing this.

You could simply give each of them an x:Name and then turn on/off IsRunning and IsVisible if you want to hide it.

I assume though that you have some data binding going on. Since IsRunning is a bool you could simply bind it to a boolean in your code behind. For instance In my ViewModel I have an IsBusy property and implement INotifyPropertyChanged:

public class MyViewModel : INotifyPropertyChanged
{


    public MyViewModel()
    {
    }

    private bool busy = false;

    public bool IsBusy
    {
        get { return busy; }
        set
        {
            if (busy == value)
                return;

            busy = value;
            OnPropertyChanged("IsBusy");
        }
    }


    public async Task GetMonkeysAsync()
    {
        if (IsBusy)
            return;


        try
        {
            IsBusy = true;

            //do stuff here that is going to take a while

        }
        finally
        {
            IsBusy = false;
        }
    }

    #region INotifyPropertyChanged implementation

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string name)
    {
        var changed = PropertyChanged;
        if (changed == null)
            return;

        changed(this, new PropertyChangedEventArgs(name));

    }

    #endregion
}

Then in the XAML you can bind to IsBusy:

<ActivityIndicator IsRunning="{Binding IsBusy}"
                       Color="Blue"/>

I think that should handle it. If you need a timer you could use the same binding that I have here and use Xamarin.Forms built in timer class.

like image 52
JamesMontemagno Avatar answered Sep 28 '22 09:09

JamesMontemagno


James' answer is correct, however, I prefer to use the page's own IsBusy property, for two reasons:

  1. I'm lazy and I don't want to set-up INotifyPropertyChanged implementation if I don't have to
  2. XF is suppossed to use that property to display a notification by default. This doesn't appear to be working, but if it ever does, this approach will already have us covered to take advantage of it

The only difference with James' answer (besides deleting the INPC implementation) is that you need to give the page a name (x:Name="myPage") and then declare the binding using a reference to it using {Binding Source={x:Reference myPage}, Path=IsBusy} for the ActivityIndicator's IsVisible and IsRunning values.

i.e.:

MainPage.xaml:

<ContentPage ... x:Name="myPage">
    ...
    <ActivityIndicator IsVisible="{Binding Source={x:Reference myPage}, Path=IsBusy}" IsRunning="{Binding Source={x:Reference myPage}, Path=IsBusy}" />
    ...
</ContentPage>

MainPage.xaml.cs:

...
async void OnDoSomethingLong(...)
{
    if (!this.IsBusy)
    {
        try
        {
            this.IsBusy = true;

            //await long operation here, i.e.:
            await Task.Run(() => {/*your long code*/});
        }
        finally
        {
            this.IsBusy = false;
        }
    }
}
...
like image 35
Sebastián Vansteenkiste Avatar answered Sep 28 '22 10:09

Sebastián Vansteenkiste