0
votes

I would like to use a numericupdown control on my application. I'm well aware that I could use a plain textbox instead, but I rather like the way this particular control's UI fits with what I'm doing in my application.

It also needs to have 0's at the left, per desired text output. If I'm not mistaken, this is not supported by standard numericupdown controls. It should never exceed 4 digits in length. However, if I input more, it must show favor to new keystrokes and drop left-most digits instead. The up and down arrows should increment/decrement the value per usual behavior. Even after keying in values.

It should never be allowed to run negative. It should only accept whole integers. This is easily handled by the stock functionality though.

1
The question in the current format is more suitable for codereview.stackexchange.com. If you want to keep it in stackoverflow, edit the post and ask a question and then post your own answer. Then it would be more useful for feature readers.Reza Aghaei
Did not know about codereview. Thanks for mentioning it. I'll go ahead and do that.Dazed.dnc

1 Answers

0
votes

Partly posting an answer for others who may follow. Partly looking for assurance that I'm not being an idiot.

Note that this hack depends on firing Sync() before extracting the final value. The timer will fire pretty quickly, but does not guarantee that things will happen in the correct order. It may not hurt to manually trigger Sync() immediately before extracting values.

public class UpDownWith0 : System.Windows.Forms.NumericUpDown
{

  private System.Windows.Forms.Timer addzeros = new System.Windows.Forms.Timer();

  public UpDownWith0()
  {
    this.addzeros.Interval = 500; //Set delay to allow multiple keystrokes before we start doing things
    this.addzeros.Stop();
    this.addzeros.Tick += new System.EventHandler(this.Sync);
  }

  protected override void OnTextBoxTextChanged(object source, System.EventArgs e)
  {
    this.addzeros.Stop(); //reset the elapsed time every time the event fires, handles multiple quick proximity changes as if they were one
    this.addzeros.Start();
  }

  public void Sync(object sender, System.EventArgs e)
  {
    int val;
    this.addzeros.Stop();
    if (this.Text.Length > 4)
    {
      //I never want to allow input over 4 digits in length. Chop off leftmost values accordingly
      this.Text = this.Text.Remove(0, this.Text.Length - 4);
    }
    int.TryParse(this.Text, out val); //could use Value = int.Parse() here if you preferred to catch the exceptions. I don't.
    if (val > this.Maximum) { val = (int)this.Maximum; }
    else if (val < this.Minimum) { val = (int)this.Minimum; }
    this.Value = val; //Now we can update the value so that up/down buttons work right if we go back to using those instead of keying in input

    this.Text = val.ToString().PadLeft(4, '0'); //IE: display will show 0014 instead of 14
    this.Select(4, 0); //put cursor at end of string, otherwise it moves to the front. Typing more values after the timer fires causes them to insert at the wrong place
  }
}