tags:

views:

23

answers:

1

Hard question to describe in one line so here's the detail.

I asked a question before about showing a busy indicator in a WPF window whilst doing some long-running action. The original question is here.

I followed some advice from a comment that suggested a kind of "DoEvents" style workaround. I know this isn't ideal but I only have a few hours to add busy indicators to about 50 windows and they all have lots of code on the UI thread that I do not have the time to modify to use background threads (I expect to be up all night sorting it without that additional headache).

So, after I set the "Busy" property in my viewmodels I run the following DoEvents style code:

Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate {  }));

Now, when I click the button that starts the long-running process, the wait indicator appears as I need it to and all is well. However, the button in question is the default button in the window. If I press Enter, the same command binding is used and I can see in debug mode that the code is visited in exactly the same way. However, the busy indicator doesn't show.

Can anyone suggest a workaround that will allow me to get some sleep tonight?

A: 

If you accept to use the "standard" Windows waiting cursor, you can simply set the Cursor property of your Window to Cursors.Wait when starting an operation and then to null at the end of the long-running operation (or use the Mouse.OverrideCursor).

I wrap this in an IDisposable class:

/// /// Helper to display a wainting cursor for the whole application /// public class WaitingCursor : IDisposable {

private Cursor m_currentCursor;

public WaitingCursor() {

    Enable();
}

/// <summary>
/// Sets the cursort to the waiting cursor
/// </summary>
public void Enable() {

    m_currentCursor = Mouse.OverrideCursor;
    Mouse.OverrideCursor = Cursors.Wait;
}

/// <summary>
/// Restores the cursor to the default one
/// </summary>
public void Disable() {
    Mouse.OverrideCursor = m_currentCursor;
}

#region Implementation of IDisposable

/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose() {
    Disable();
}

#endregion

}

Then, one can simply write:

using (new WaitingCursor()) {

   ... // long-running op
}
Timores
Gave it a try. Annoyingly has similar problems. If I click the button, all is good. Is I hit Enter, sometimes it works, other times the cursor vanishes when it is within the boundaries of the window.
Unhappy
...and weirdly, when I use it NUnit gives me the error, "The calling thread must be STA, because many UI components require this"
Unhappy
That second problem was the Mouse.OverrideCursor property requiring STA thread. Had to drop that bit out whilst in test mode.
Unhappy
I am sorry about your problems. You must have some very special requirements, as I have used this class in several projects, without any problem. As far as I know, STA requirement is a given for any GUI project.
Timores