Input only digits and control buttons

217 Views Asked by At

I want to input Salary with any value: 550,49, 2222,12, 9,3 and so on. But need to use control button like this: ,, backspace, ctrl + c, ctrl + v, ctrl + a.

Salary is TextBox with ShortcutsEnabled = true and event:

private void TbSalary_KeyPress(object sender, KeyPressEventArgs e)
{
    char number = e.KeyChar;
    if ((e.KeyChar <= 47 || e.KeyChar >= 58) && number != 8 && number != 44) 
         //digits, BackSpace and ,
    {
        e.Handled = true;
    }
}

If remove this condition, the specified combinations will work. But not only numbers are entered.

Should I add tracking of all combinations here? Or is it possible to implement this task in another way?

MaskedTextBox requires a fixed number of characters with some "mask". But the Salary is different. Can be **,**, ******,* or *** and etc.

UPDATE

Prevent entering more than two numbers after the decimal point

if (number < ' ')
{
    return;
}
if (number >= '0' && number <= '9')
{
    if (this.Text.Contains(',') 
        && this.SelectionLength == 0
        && this.SelectionStart > this.Text.IndexOf(',')
        && this.Text.Length - this.Text.IndexOf(',') > 2)
    {
        e.Handled = true;
    }

    return;
}
1

There are 1 best solutions below

8
Dmitry Bychenko On BEST ANSWER

Please, don't use magic numbers like 47, let's work with characters. We should allow these characters:

  • '0'..'9' range (numbers)
  • control characters (which are below space ' ') for tab, backspace etc.
  • ',' (comma) as a decimal separator

All the other characters should be banned.

Code:

private void TbSalary_KeyPress(object sender, KeyPressEventArgs e)
{
    char number = e.KeyChar;
    TextBox box = sender as TextBox;

    if (number >= '0' && number <= '9' || number < ' ')
        return; // numbers as well as backspaces, tabs: business as usual
    else if (number == ',') {  
        // We don't want to allow several commas, right?
        int p = box.Text.IndexOf(',');

        // So if we have a comma already...
        if (p >= 0) { 
            // ... we don't add another one
            e.Handled = true;

            // but place caret after the comma position
            box.SelectionStart = p + 1;
            box.SelectionLength = 0;  
        }  
        else if (box.SelectionStart == 0) {
            // if we don't have comma and we try to add comma at the 1st position 
            e.Handled = true;

            // let's add it as "0,"
            box.Text = "0," + box.Text.Substring(box.SelectionLength);
            box.SelectionStart = 2;
       } 
    }
    else  
        e.Handled = true; // all the other characters (like '+', 'p') are banned
}

Please, note, that there is possibility to Paste incorrect value (say, "bla-bla-bla") into TbSalary TextBox; to prevent it you can use TextChanged event:

private void TbSalary_TextChanged(object sender, EventArgs e) {
  TextBox box = sender as TextBox;

  StringBuilder sb = new StringBuilder();

  bool hasComma = false;

  foreach (var c in box.Text)
    if (c >= '0' && c <= '9')
      sb.Append(c);
    else if (c == ',' && !hasComma) {
      hasComma = true;

      if (sb.Length <= 0) // we don't start from comma
        sb.Append('0');

      sb.Append(c);
    }

  string text = sb.ToString();

  if (!text.Equals(box.Text))
    box.Text = text;
}