code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
public static class BusyIndicator { private static readonly AsyncCallback nullCallback = delegate { }; private static readonly object[] emptyArray = new object[] { }; public static void ShowWhile(Control control, ThreadStart method) { if (method == null) throw new ArgumentException("Missing method definition", "method"); if (control == null) { method.BeginInvoke(nullCallback, emptyArray); return; } control.Cursor = Cursors.WaitCursor; MethodInvoker callback = delegate { control.Cursor = Cursors.Default; }; AsyncCallback invoke = delegate { control.Invoke(callback); }; method.BeginInvoke(invoke, emptyArray); } }
sample usage
1 2 3 4
BusyIndicator.ShowWhile(this, delegate { // Do stuff });
Refactorings
No refactoring yet !
Darius Damalakas
September 27, 2007, September 27, 2007 00:34, permalink
Seems ok to me. I doubt if refactoring could make it more readable.
Of course, unless you have many of such busy indicators, and of various kinds.
If it's the only busy indicators, then its very fine
D_Guidi
September 27, 2007, September 27, 2007 00:41, permalink
I've tested the code and this indicator is something like "Control-specific": this means that the BusyIndicator is showed only when the mouse is under the specific control, and not globally showed (better solutions exists for a global busy indicator using Cursor.Current).
This means that you could use (i think) more than one of this snippets at the same time, using different components as "host".
Now a better solution for a global wait cursor.
code provided by Marco De Sanctis
1 2 3 4 5 6 7 8 9 10 11
public class WaitCursor: IDisposable { public WaitCursor() { Cursor.Current = Cursors.WaitCursor; } public void Dispose() { Cursor.Current = Cursors.Default; } }
usage
1 2 3 4
using (new WaitCursor()) { // some code here }
Darius Damalakas
September 27, 2007, September 27, 2007 02:12, permalink
One problem with the original code is that after the method is invoked, it resets controls cursor to Cursors.Default, which might be not what was before.
Imagine, that the cursor was a magnify glass, and after the call it gets reset to Cursor.Default. IMHO, that's not what we want. We want the code to reset the cursor to previous state.
No code examples, since that's trivial to implement.
D_Guidi
September 28, 2007, September 28, 2007 00:10, permalink
I agree with you, Darius.
Simply, i need to store cursor's status in a field before the invoke, and use this field to restore the correct status in the callback.
Thanks for the suggest ;)
P.S: this service is so cool :)
Avish
September 28, 2007, September 28, 2007 01:30, permalink
Under .NET 2.0 and onwards, you can also use the UseWaitCursor property. This overrides other cursor settings without changing them, so once you set it to false again you automatically get your old cursor back.
1 2 3 4 5 6 7 8 9 10 11 12
public class WaitCursor: IDisposable { public WaitCursor(Form form) { form.UseWaitCursor = true } public void Dispose() { form.UseWaitCursor = false } }
D_Guidi
September 28, 2007, September 28, 2007 03:41, permalink
Cool :)
A suggest, You could (i think, looking at msdn: http://tinyurl.com/26rqaq) use a Control instead of a Form as a parameter... right?
1 2 3 4 5 6 7 8 9 10 11 12
public class WaitCursor: IDisposable { public WaitCursor(Control control) { control.UseWaitCursor = true } public void Dispose() { control.UseWaitCursor = false } }
Nathan
October 1, 2007, October 01, 2007 10:37, permalink
control.FindParent will find the form the control is on. Then you can set the cursor for the entire form.
JH
October 23, 2007, October 23, 2007 13:38, permalink
If I were using this in an MVP pattern I would try to leave the implementation of the wait state up to the view. This way I can re-use the code in an ajax control (set some visual wait indicator) or a winforms application (set the wait cursor).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
public interface IView { void ShowWaitState(); void ShowReadyState(); } public class Presenter { private IView view; public Presenter(IView view) { this.view = view; } public void DoSomething() { view.ShowWaitState(); // ... view.ShowReadyState(); } }
Show a BusyIndicator during long-tasks execution.