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