MVVM Wait Cursor how to set the.wait cursor during invocation of a command?

user1328350 picture user1328350 · Apr 12, 2012 · Viewed 22.3k times · Source

Scenario: User clicks a button on the View This invokes a command on the ViewModel, DoProcessing How, and where does the Wait cursor get set, considering the responsibilitues of View and ViewModel?

Just to be clear, I am just looking to change the DEFAULT cursor to an hourglass while the command is running. When the command completes, the cursor mut change back to an arrow. (It is a synchronous operation I am looking for, and I want the UI to block).

I have created an IsBusy property on the ViewModel. How do I ensure that the Application's mouse pointer changes?

Answer

Shakti Prakash Singh picture Shakti Prakash Singh · Apr 12, 2012

I am using it successfully in my application:

/// <summary>
///   Contains helper methods for UI, so far just one for showing a waitcursor
/// </summary>
public static class UIServices
{
    /// <summary>
    ///   A value indicating whether the UI is currently busy
    /// </summary>
    private static bool IsBusy;

    /// <summary>
    /// Sets the busystate as busy.
    /// </summary>
    public static void SetBusyState()
    {
        SetBusyState(true);
    }

    /// <summary>
    /// Sets the busystate to busy or not busy.
    /// </summary>
    /// <param name="busy">if set to <c>true</c> the application is now busy.</param>
    private static void SetBusyState(bool busy)
    {
        if (busy != IsBusy)
        {
            IsBusy = busy;
            Mouse.OverrideCursor = busy ? Cursors.Wait : null;

            if (IsBusy)
            {
                new DispatcherTimer(TimeSpan.FromSeconds(0), DispatcherPriority.ApplicationIdle, dispatcherTimer_Tick, System.Windows.Application.Current.Dispatcher);
            }
        }
    }

    /// <summary>
    /// Handles the Tick event of the dispatcherTimer control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private static void dispatcherTimer_Tick(object sender, EventArgs e)
    {
        var dispatcherTimer = sender as DispatcherTimer;
        if (dispatcherTimer != null)
        {
            SetBusyState(false);
            dispatcherTimer.Stop();
        }
    }
}

This has been taken from here. Courtsey huttelihut.

You need to call the SetBusyState method every time you think you are going to perform any time consuming operation. e.g.

...
UIServices.SetBusyState();
DoProcessing();
...

This will automatically change your cursor to wait cursor when the application is busy and back to normal when idle.