Home > Mobile >  Regex.IsMatch not working after backspace in TextBox.Text
Regex.IsMatch not working after backspace in TextBox.Text

Time:09-17

I have a TextBox with a LostFocus event handler that calls a method that formats the string of numbers in the TextBox to a number format. For instance, 123456,78 returns 123 456,78.
If I instead start with 123 45 it correctly returns 12 345,00.

However, if I first type 123456,78, and it correctly returns 123 456,78, and then delete the last four characters in the TextBox with the backspace key, i.e. I delete 6,78 by clicking backspace four times, it's not working. It just keeps 123 45 in the TextBox.
However, if I select all the text in the TextBox and paste 123 45 it returns 12 345,00 correctly.

When I debug by stepping one line at a time, I see that the method argument amountIn correctly stores the string 123 45, both when I use the backspace keys and when I select and paste. However, Regex.IsMatch() returns false when I use backspace and true when I select and paste. Hence, I believe that the backspace leaves some kind of artifact in the string that is not visible while debugging but is recognized by the IsMatch() method. Here is my method:

private void txtAmount_LostFocus(object sender, EventArgs e)
{
    txtAmount.Text = ReformatAmount(txtAmount.Text);
}

public static string ReformatAmount(string amountIn)
{
    string amountOut;
    if (Regex.IsMatch(amountIn, @"^[0-9 ,.] $"))
    {
        amountOut = Regex.Replace(amountIn, "[. ]", "");

        amountOut = Convert.ToDecimal(amountOut).ToString("N");

        return amountOut;
    }
    else
    {
        amountOut = amountIn;
        return amountOut;
    }
}

CodePudding user response:

The CultureInfo.NumberFormat.NumberGroupSeparator in Sweden is the non-breaking space character, char 0xA0 (160), not char 0x20 (32), the white space commonly used to separate, e.g, words.

You can see it better writing:

var cultureSE = CultureInfo.GetCultureInfo("se-SE");
string hexChar = ((int)cultureSE.NumberFormat.NumberGroupSeparator[0]).ToString("X2");

hexChar will be "A0".

The Regex in use, ^[0-9 ,.] $ doesn't account for that, it only considers char 0x20.
You can change it to just [0-9 ,.] to ignore it, but you probably want to use \s instead, it will also match all Unicode white-space chars, including non-breaking white-space chars, as char 0xA0.
See also: Character classes in regular expressions

The expression can then be changed in:

if (Regex.IsMatch(amountIn, @"^[0-9\s,.] $"))
{
     // Convert to a culture-specific number representation
}

CodePudding user response:

No need for regular expressions:

string[] nums = new[]
{
  "123456,78",
  "123 456,78",
  "6,78",
  "123 45"
};
foreach (var num in nums)
{
  if (Decimal.TryParse(num, NumberStyles.Any, null, out decimal result))
  {
    // Number successfully parsed:
    Console.WriteLine($"{result:N2}");
  }
  else
  {
    // Parsing error here
    Console.WriteLine($"Could not parse: '{num}'");
  }
}

Output:

123 456,78
123 456,78
6,78
12 345,00
  • Related