Wer kennt es in der UI-Programmierung nicht: immer wieder den selben Programmcode für die Sanduhr! Hier soll eine handliche Lösung aufgezeigt werden wie man die Sanduhr mit wenigen Zeilen in eigenen Programme einbinden kann.

Der folgende Code kennen vermutlich die meisten und soll vereinfacht werden:

public void DoSomething()
{
  Cursor.Current = Cursors.WaitCursor;
  try
  {
    DoSomethingMore();
  }
  finally
  {
    Cursor.Current = Cursors.Default;
  }
}

Nachdem der Cursor auf den WaitCursor (Sanduhr) umgestellt wurde, wird mittels eines Try-Finally-Blockes sichergestellt, das die Sanduhr auf jedenfall wieder zurück gestellt wird, auch wenn innerhalb des Try's ein schwehrwiegender Fehler (=Exception) auftritt. Es soll also nie eine Sanduhr "stehenbleiben", weil im Code ein Fehler aufgetreten ist.

Nun kannte ich von früher her noch das Guard-Pattern (Pattern = Programmiermuster), welches dazu gedacht ist einen Codeblock betreffend eines Aspektes abzusichern. In unserem Fall ist der Aspekt der WaitCursor. Habe mir dann eine kleine WaitCursor-Klasse zusammen gebaut, welche mir mit Hilfe des using-Schlüsselwortes von C# erlaubt folgenden Code zu schreiben:

public void DoSomething()
{
  using (WaitCursor.Show())
  {
    DoSomethingMore();
  }
}

Ist doch nett und viel kürzer. Ausserdem wird verhindert, das ich den Finally vergesse oder gar falsch implementiere.

Und hier die WaitCursor-Klasse:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
 
namespace iDev.Lib.Gui.WinForms
{
    /// 
    /// Showns a hourglass cursor and restores the cursor when the instance gets disposed.
    /// 
    /// using (WaitCursor.Show())
    /// {
    /// ... do something ...
    /// }
    public class WaitCursor : IDisposable
    {
        #region Constructor(s)
 
        public WaitCursor()
        {
            // Save the current cursor
            m_OldCursor = Cursor.Current;
 
            // Set the WaitCurcor
            Cursor.Current = Cursors.WaitCursor;
        }
 
        #endregion
 
        #region Public Methods
 
        /// 
        /// Backup the current cursor and shows a wait cursor.
        /// 
        /// using (WaitCursor.Show())
        /// {
        /// ... do something ...
        /// }
        public static WaitCursor Show()
        {
            return new WaitCursor();
        }
 
        #endregion
 
        #region IDisposable Members
 
        public void Dispose()
        {
            // Restore the previous cursor
            if (m_OldCursor != null)
            {
                Cursor.Current = m_OldCursor;
            }
            else
            {
                Cursor.Current = Cursors.Default;
            }
        }
 
        #endregion
 
        #region Private members
 
        Cursor m_OldCursor = null;
 
        #endregion
    }
}