Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 734
user1328350 Avatar asked Apr 12 '12 06:04

user1328350


People also ask

How do I change my cursor in WPF?

A switch statement filters on the cursor name and sets the Cursor property on the Border which is named DisplayArea. If the cursor change is set to "Entire Application", the OverrideCursor property is set to the Cursor property of the Border control. This forces the cursor to change for the whole application.

What is cursor wait?

The Windows wait cursor, informally the Blue circle of death (known as the hourglass cursor until Windows Vista) is a cursor that indicates that an application is busy performing an operation. It can be accompanied by an arrow if the operation is being performed in the background.

How do I change my cursor to hourglass in C#?

Hourglass Cursor [C#] If you want to change the mouse cursor at application level use static property Current of Cursor class. To show hourglass cursor assign value Cursors. WaitCursor. To return back the default behavior (to display control specific cursor) assign back value Cursors.


3 Answers

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.

like image 102
Shakti Prakash Singh Avatar answered Nov 09 '22 01:11

Shakti Prakash Singh


A very simple method is to simply bind to the 'Cursor' property of the window (or any other control). For example:

XAML:

<Window
    x:Class="Example.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     Cursor="{Binding Cursor}" />

ViewModel Cursor Property (Using Apex.MVVM):

    private NotifyingProperty cursor = new NotifyingProperty("Cursor", typeof(System.Windows.Input.Cursor), System.Windows.Input.Cursors.Arrow);
    public System.Windows.Input.Cursor Cursor
    {
        get { return (System.Windows.Input.Cursor)GetValue(cursor); }
        set { SetValue(cursor, value); }
    }

Then simply change the cursor in your view when needed...

    public void DoSomethingLongCommand()
    {
        Cursor = System.Windows.Input.Cursors.Wait;

        ... some long process ...

        Cursor = System.Windows.Input.Cursors.Arrow;
    }
like image 43
bradcarman Avatar answered Nov 09 '22 00:11

bradcarman


You want to have a bool property in viewmodel.

    private bool _IsBusy;
    public bool IsBusy 
    {
        get { return _IsBusy; }
        set 
        {
            _IsBusy = value;
            NotifyPropertyChanged("IsBusy");
        }
    }

Now you want to set the window style to bind to it.

<Window.Style>
    <Style TargetType="Window">
        <Setter Property="ForceCursor" Value="True"/>
        <Style.Triggers>
            <DataTrigger Binding="{Binding IsBusy}" Value="True">
                <Setter Property="Cursor" Value="Wait"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Style>

Now whenever a command is being executed and your view model is is busy, it would just set the IsBusy flag and reset it when done. The Window will automatically display the wait cursor and restore the original cursor when done.

You can write the command handler function in view model something like this:

    private void MyCommandExectute(object obj) // this responds to Button execute
    {
        try
        {
            IsBusy = true;

            CallTheFunctionThatTakesLongTime_Here();
        }
        finally
        {
            IsBusy = false;
        }
    }
like image 38
zar Avatar answered Nov 09 '22 00:11

zar