How to implement Activity/Wait Indicator in dotnet Maui?
Asked Answered
D

2

5

I needed to implement a wait indicator for a page in my Maui app.

Searching gave me this, but no step by step instructions.

So how do I do this?

Deaminate answered 3/1, 2023 at 22:25 Comment(0)
D
7

Overview:

  • The control to display the animation is called ActivityIndicator.
  • ActivityIndicator is a visual element, should be part of your page.
    So, add an ActivityIndicator to your xaml.
  • The state of the indicator is part of logic - should live in your view model.
    So, add a bindable property to your view model, and bind ActivityIndicator.IsRunning to this property.

Sample (I haven't tested, just for illustration)
Page (xaml):

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:customcontrols="clr-namespace:Waiter.Maui.CustomControls"
             x:Class="..." >

    <ContentPage.Content>
        <ActivityIndicator IsRunning="{Binding IsBusy}" />
        <Button Text="Go" Command="{Binding GoCommand}" />
    </ContentPage.Content>
</ContentPage>

ViewModel:

namespace MyNamespace
{
    public class MyViewModel : BaseViewModel
    {
        public MyViewModel()
        {
            GoCommand = new Command(execute: OnGo, canExecute: true);
        }

        public Command GoCommand { get; }
        private void OnGo()
        {
            MainThread.InvokeOnMainThreadAsync(async () =>
            {
                IsBusy = true;
                Thread.Sleep(5000);
                IsBusy = false;
                return result;
            });
        }
    }
}

BaseViewModel class (so that it can be re-used, from existing community content):

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace Waiter.Maui.Pages
{
    public class BaseViewModel : INotifyPropertyChanged
    {
        bool isBusy = false;
        public bool IsBusy
        {
            get { return isBusy; }
            set { SetProperty(ref isBusy, value); }
        }

        string title = string.Empty;
        public string Title
        {
            get { return title; }
            set { SetProperty(ref title, value); }
        }

        protected bool SetProperty<T>(ref T backingStore, T value,
            [CallerMemberName] string propertyName = "",
            Action onChanged = null)
        {
            if (EqualityComparer<T>.Default.Equals(backingStore, value))
                return false;

            backingStore = value;
            onChanged?.Invoke();
            OnPropertyChanged(propertyName);
            return true;
        }

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            var changed = PropertyChanged;
            if (changed == null)
                return;

            changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }
}
Deaminate answered 3/1, 2023 at 22:25 Comment(0)
C
3

I want to point out few things.

First of all, this "IsBusy" that I see getting recommended all around, is working strategy. I can only recommend using CommunityToolkit.MVVM, and letting it do your job, and handle all notification code instead of you.

However, using such boolean variable, is no different than using Lock, Mutex, Semaphore, etc. A programmer has to be very careful how and when it is changed, otherwise all kinds of bugs may occur.

In reality, most problems can be solved with commanding itself. Specifically CanExecute property is more than enough.

I recommend this: https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/data-binding/commanding?view=net-maui-7.0

Before becoming slave to manual changing bool variables.

Currency answered 3/1, 2023 at 23:36 Comment(2)
It would be helpful if you add (or point to) a code sample that explains how CommunityToolkit.MVVM can handle ActivityIndicator?Heywood
@Heywood "I need to implement wait indicator", believe it or not, does not correspond to dealing with ActivityIndicator. His search result pointed to that page, but the solution may be implemented with pop-up service (understand as native dialog), overlay control (understand as native View) or something entirely different. My point here is that manually controlling IsBusy is not the way to implement it. This is manual lock. Mutex. Semaphore. This is used all around (as you can see, accepted and upvoted answer) , but the downside is that you are at constant risk of locking yourself.Currency

© 2022 - 2024 — McMap. All rights reserved.