user2853648
user2853648

Reputation: 73

Creating base loading view with prism

My prism application has a lot of async operations called from my view models. In some cases, I want the view to be disabled and display some kind of busy indicator until the viewmodel gets back the result from the async operation.

I though of creating a base view which will implement this behavior (i.e have a dependency property of IsLoading which will disable the view and display a busy indicator above it). The problem is, I'm not sure how to implement this base view. Any help would be appreciated, thanks.

Edit: I wrote a LoadingView which does the job, I think.

public class LoadingView : UserControl { private object content;

    public bool IsLoading
    {
        get
        {
            return (bool)GetValue(IsLoadingProperty);
        }
        set
        {
            SetValue(IsLoadingProperty, value);
        }
    }

    private ProgressRing m_RingControl;

    public LoadingView()
    {
        m_RingControl = new ProgressRing();
        m_RingControl.IsActive = false;
    }

    // Using a DependencyProperty as the backing store for IsLoading.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsLoadingProperty =
        DependencyProperty.Register("IsLoading", typeof(bool), typeof(LoadingView), new PropertyMetadata(false, IsActivePropertyChanged));

    private static void IsActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        LoadingView view = d as LoadingView;
        if (view != null)
        {
            // Loading - show ring control
            if (((bool)e.NewValue) == true)
            {
                view.content = view.Content;
                view.Content = view.m_RingControl;
                view.m_RingControl.IsActive = true;
            }
            else
            {
                view.m_RingControl.IsActive = false;
                view.Content = view.content;
            }
        }
    }
}

and i put binding on LoadingView.IsLoading with some IsLoading (or IsBusy) in the viewmodel

Upvotes: 2

Views: 441

Answers (1)

slugster
slugster

Reputation: 49974

This is a subject that can get really complex really fast.

I would advise a small change in approach - instead of putting an IsBusy property in a base viewmodel, instead make it abstract so that each derived viewmodel has to implement its own specific check.

public class BaseViewModel : INotifyPropertyChanged
{

    public abstract bool IsBusy { get; }

}

public class FancyViewModel : BaseViewModel
{

    public override bool IsBusy
    {
        get { return [check #1] && [check #2]...; }
    }
}

Now it is up to each specific viewmodel to determine whether it is busy. A crude mechanism is to have a counter which you increment every time an async function is kicked off, and decrement it when the operation ends - if its value is equal to zero then there are no current async operations. When using flags or counters be aware of various property reading issues that can occur because of compiler optimisations, learn to use the volatile keyword in the right place.

Alternatively instead of keeping a counter you could use the thread safe CountdownEvent class. If you want to get really advanced then you can check out the various thread signalling mechanisms in the System.Threading namespace, or look at task parallelism and the Task object.

Upvotes: 2

Related Questions