Creating a hexadecimal control NumericUpDown

advertisements

I have created a hexadecimal NumericUpDown control by sub-classing the basic NumericUpDown and adding the following method:

protected override void UpdateEditText()
{
  this.Text = "0x" + ((int) Value).ToString("X2");
}

This works pretty well. The control now shows values in the format:

0x3F

which is exactly what I was after.

But one thing bothers me: every time the Text-property is assigned, a System.FormatException is thrown. This doesn't seem to affect the control's functionality, but still I think it's ugly.

This is the top of the callstack:

MyAssembly.dll!HexNumericUpDown.UpdateEditText() Line 31 C# System.Windows.Forms.dll!System.Windows.Forms.NumericUpDown.ValidateEditText() Unknown System.Windows.Forms.dll!System.Windows.Forms.UpDownBase.Text.set(string value) Unknown

Can I just ignore this exception? Or is there a clean way to get rid of this?


You need to override the ValidateEditText() method so you can properly handle the (optional) "0x" prefix. And override UpdateEditText() to prefix "0x". Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox onto your form:

using System;
using System.Windows.Forms;

class HexUpDown : NumericUpDown {
    public HexUpDown() {
        this.Hexadecimal = true;
    }

    protected override void ValidateEditText() {
        try {
            var txt = this.Text;
            if (!string.IsNullOrEmpty(txt)) {
                if (txt.StartsWith("0x")) txt = txt.Substring(2);
                var value = Convert.ToDecimal(Convert.ToInt32(txt, 16));
                value = Math.Max(value, this.Minimum);
                value = Math.Min(value, this.Maximum);
                this.Value = value;
            }
        }
        catch { }
        base.UserEdit = false;
        UpdateEditText();
    }

    protected override void UpdateEditText() {
        int value = Convert.ToInt32(this.Value);
        this.Text = "0x" + value.ToString("X4");
    }
}

Fwiw, the quirky try/catch-em-all comes straight from the .NET version. I kept it to make the control behave the same way. Tweak the ToString() argument the way you want it.