Here’s an interesting utility class, a scoped value. This allows you to have a member variable that gets changed for a time, and then automatically restored back to the original value.

Looked at another way, a Scoped is a member variable where changes are not permanent. Instead, changes are kept during a particular scope of execution, then reverted.

When is this useful?

One sample use is for the mouse cursor - with a suitably configured Scoped you can simply change the cursor to an hour glass during a process and then have it automatically restored again afterwards.

using (screenCursor.As(Cursors.HourGlass))
{
    // Long running action
}

Contrast this with the code often written for this situation:

Control.Cursor = Cursors.HourGlass;
try
{
    // Long running action
}
finally
{
    Control.Cursor = Cursors.Default;
}

One major issue with this code is that it doesn’t support nesting - when this particular block completes, the cursor is restored to its default value, even if this block has been called as a part of processing a larger piece of work. Of course, this can be easily addressed by caching the existing value in a temporary variable, but this increases the amount of boilerplate code required.

Using a Scoped takes care of these details, leaving you to focus on the core logic that needs your attention.

Setup is relatively straightforward, just create a Scoped member variable and hook up a handler to the ValueChanged event.

Here’s a full example …

public class ExampleForm : Form
{
    public ExampleForm()
    {
        mScreenCursor = new Scoped<Cursor>(Cursors.Default);
        mScreenCursor.ValueChanged += UpdateCursor;
    }

    private void UpdateCursor(
        object sender,
        ValueChangedEventArgs<Cursor> args)
    {
        Cursor = args.Value;
    }

    private readonly Scoped<Cursor> mScreenCursor;
}

Comments

blog comments powered by Disqus