How do I validate a price (number) textbox? - c#

I have a Windows forms application written in C#.
I am looking for a way to validate my price textBox so that it only accepts prices in a double format e.g. allowing 0.01 & 1200.00 but provides an error when the user enters characters.
I would except the code to looks similar to
String price = tbx_price.Text.Trim();
if price is not a number
{
error message
}
else{
...
What method could I use to check if the price string contains only numbers? Please note that I require the user to be able to use decimal places so the '.' character should be allowed.

Use decimal.TryParse :
decimal d;
if (!decimal.TryParse(price, out d)){
//Error
}
And if you also want to validate the price (145.255 is invalid):
if (!(decimal.TryParse(price, out d)
&& d >= 0
&& d * 100 == Math.Floor(d*100)){
//Error
}

You can test this using decimal.TryParse().
For example:
decimal priceDecimal;
bool validPrice = decimal.TryParse(price, out priceDecimal);
If you can't be sure that the thread culture is the same as the user's culture, instead use the TryParse() overload which accepts the culture format (also the number format which you can set to currency):
public bool ValidateCurrency(string price, string cultureCode)
{
decimal test;
return decimal.TryParse
(price, NumberStyles.Currency, new CultureInfo(cultureCode), out test);
}
if (!ValidateCurrency(price, "en-GB"))
{
//error
}

Besides using the answer marked as accepted in order to avoid the problem with culture about prices, you can always use this
Convert.ToDouble(txtPrice.Text.Replace(".", ","));
Convert.ToDouble(txtPrice.Text.Replace(",", "."));
this will depend how you manage your convertion in your app.
PS: I could not comment the answer because i do not have the neccesary reputation yet.

Related

How can i convert string value to rial money unit?

I'm beginner in c# and have this value of string:
123456
but want convert that string to my country money, want convert that string value to this:
123,456
always split three numbers with comma for example, if string number is this:
1234567890
Show to user this:
1,234,567,890
How can i write code that purpose?
I would suggest convert it to int (or long) first and then use ToString() and supply required format.
int number = int.Parse(numberString); //ex..
number.ToString("N0"); // 1,000,000
If you're asking about culture-specific formatting, then you could do this.
number.ToString("N0", CultureInfo.CreateSpecificCulture("es-US"));
You can explore more on standard numeric formats
Example code
Use the standard formatters and the CultureInfo for the desired country.
e.g
int i = int.Parse("123456");
string money = i.ToString("C", CultureInfo.CreateSpecificCulture("fr-Ir"));
Or if the system culture is fr-Ir
string money = i.ToString("C");
Which is the same as
string money = i.ToString("C", CultureInfo.CurrentCulture);
Or if you want to use the UI culture (the culture of the requesting browser)
string money = i.ToString("C", CultureInfo.CurrentUICulture);
Since you want to convert your value to currency, I would suggest using "C" of string formats provided by .NET.
123456.125M.ToString("C"); // $123,456.13
Sign infront of the string will be defined by the culture of your machine. More information here.
On the other hand, there is another solution to add your own custom format:
123456.125M.ToString("#,0.################"); // 123,456.125
It is not the clean way, but I have not since found a correct way of actually formating this in generic way.
Side note: for currency handling it is generally considered a good practise to use decimal. Since it does not have a floating point issue.
Please try this one hope will help
Just whats inside the void method
using System.Linq;
public class Program
{
public void ABC()
{
var data = "123456789";
const int separateOnLength = N;
var separated = new string(
data.Select((x,i) => i > 0 && i % separateOnLength == 0 ? new [] { ',', x } : new [] { x })
.SelectMany(x => x)
.ToArray()
);
}
}

Regex to validate price (type of decimal)

I have looked through stackoverflow trying to find a solution to this but with no luck so hence why I have resulted in asking the question..
I have a field on my form which is price, type of decimal this is optional depending on what they have selected from a dropdown, So I cant use the [Required] attribute.
When the form is submitted if they have chosen a value from the dropdown which requires the user to enter a postage price I then need to check this field to make sure its a valid decimal so to do this I have the following
public static bool IsValid(decimal postagePrice)
{
var regex = new Regex(#"^\d+.\d{0,2}$");
return regex.IsMatch(postagePrice);
}
But it complains and says "Argument type decimal is not assignable to parameter type string" which I understand, I also can't use Decimal.TryParse as that expects a string.
How can I resolve this (I'm not in a position to change the type from decimal to string either)
If all you want is to verify that the value has at most two decimal positions, you could use a modulo:
public static bool IsValid(decimal postagePrice)
{
return postagePrice % 0.01m == 0m;
}
Regular expressions work on strings - it's that simple.
So in one way or another you'll need to covert the decimal to a string before using a regex to validate it.

Parse String to Decimal using any decimal seperator

I want to parse a string from an Text input to decimal. The value represents a currency value.
Currently i got this solution:
private Decimal CastToDecimal(string value)
{
Decimal result;
var valid = Decimal.TryParse(value, NumberStyles.Currency, null, out result);
return valid ? result : -1;
}
This works pretty well so far, except for possible culture-differences. I'm german and i expect most users to enter german-style puctuation. But it is possible that someone uses "." instead of "," and the conversion will fail.
"123,45€" => 123.45
"123.456,78€" => 123456.78
"123.45€" => 12345 <- I want the result to be 123.45 here
Is there a way to automatically detect the used culture for a decimal value? Such that it does not matter if you use german or english punctuation, you still get the same result?
Update:
Thanks to your help, i created a method which does what i want (i think).
private static Decimal CastToDecimal(string value)
{
Decimal resultDe;
Decimal resultEn;
var style = NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands;
var cultureDe = CultureInfo.CreateSpecificCulture("de-DE");
var cultureEn = CultureInfo.CreateSpecificCulture("en-GB");
var deValid = Decimal.TryParse(value, style, cultureDe, out resultDe);
var enValid = Decimal.TryParse(value, style, cultureEn, out resultEn);
var minVal = Math.Min(resultDe, resultEn);
var maxVal = Math.Max(resultDe, resultEn);
if (!deValid)
return resultEn;
if (!enValid)
return resultDe;
return BitConverter.GetBytes(decimal.GetBits(minVal)[3])[2] > 2 ? maxVal : minVal;
}
This code...
Console.WriteLine(CastToDecimal("123,45"));
Console.WriteLine(CastToDecimal("123.45"));
Console.WriteLine(CastToDecimal("123,450"));
Console.WriteLine(CastToDecimal("123.450"));
Console.WriteLine(CastToDecimal("123.123,45"));
Console.WriteLine(CastToDecimal("123,123.45"));
returns this:
123,45
123,45
123450
123450
123123,45
123123,45
the solution at http://msdn.microsoft.com/en-us/library/3s27fasw%28v=vs.110%29.aspx
which includes setting the NumberStyle may be helpful.
...
value = "1.345,978";
style = NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands;
culture = CultureInfo.CreateSpecificCulture("es-ES");
if (Double.TryParse(value, style, culture, out number))
Console.WriteLine("Converted '{0}' to {1}.", value, number);
else
Console.WriteLine("Unable to convert '{0}'.", value);
// Displays:
// Converted '1.345,978' to 1345.978.
value = "1 345,978";
if (Double.TryParse(value, style, culture, out number))
Console.WriteLine("Converted '{0}' to {1}.", value, number);
else
Console.WriteLine("Unable to convert '{0}'.", value);
...
I encountered the same problem some time ago. My solution was writing my own parser in Java. The algorithm first cleans up the string. Brief description follows:
Scan string from left to right
If char = '.' then dotFound=true ; lastSeparatorPosition = index ; dots++
If char = ',' then commaFound=true ; lastSeparatorPosition = index ; commas++
If dots == 0 && commas == 0 then its an integer => done
If dots > 0 && commas > 0 then the one at lastSeparatorPosition is the decimal separator. Remove the others from the string => done
/* only one separator type */ if ( dots + commas ) > 1 then remove them // because must be thousands separator => done
/* separator occurs once */ if numberOfDigits right of separator == 3 then you have to decide :-) either integer or decimal with 3 digits in fraction
7 is the only remaining problem like chiastic-security already stated. Here you can only decide taken the conceptual environment into account. All other cases are safe.
Have fun
This can't be done, simply because there are strings that are meaningful in two different cultures, but mean different things. For instance:
123.456
123,456
The first is a bit over 123 in the UK, but 123456 in Germany; the second is 123456 in the UK but a bit over 123 in France.
The only solution is to add validation on input and give user and example by the way if it is a webpage then find a way to get input according to user's culture. I suggests you to not to try to do what you are trying because there are some culture which contradict each others for example in currency;
US/Australia/Many others uses following format
45,999.95
where , is thousand separator and . is decimal separator
whereas in some European countries
45.999,95
means the same as above but thousands separator is . and , is used as decimal separator.
Now issue is there is no guarantee that user use both separator and your system may assume thousand separator as decimal and so on.
If you really don't want to bother user then make separate input fields for major and minor currencies.
So its better to not to go there. I believe this may help. Happy Coding :)
Update:
Same case is with date format e.g. in US format month comes first and then day whereas in Australia day comes first and then month now 02/01/2015 input will mean differently system can't tell the intention of user.

forcing four decimal places for double

I need to display particular value to 4 decimal places for sure.
Here is the code
row["Money"] = StringMgt.ToGlobalizationString("N4", dblMoney);
public static string ToGlobalizationString(string format, double dblNumber)
{
return dblNumber.ToString(format, CultureInfo.CreateSpecificCulture(CultureInfo.CurrentCulture.Name));
}
Which outputs
1.4305228 to 1.4305 (which is fine!)
0.30704454 to 0.307 (I need to display 4 decimal places consistently)
How do I force it to display four decimal places (ex 0.3070)? I have seen similar posts but did not understand properly.
Thanks.
So the way I understand it you need exactly four decimals, otherwise pad with 0 to the right. So it should be .ToString("0.0000").
I'd use the F-Format specifier:
void Main()
{
double input = 3.213112134;
string result = input.ToGlobalizationString("F4").Dump();
}
public static class Extensions
{
public static string ToGlobalizationString(this double input, string format)
{
return input.ToString(format, CultureInfo.CreateSpecificCulture(CultureInfo.CurrentCulture.Name));
}
}
This will return a string with 4 decimal points. Change it to your liking.
Use following format:
row["Money"] = StringMgt.ToGlobalizationString("0.0000", dblMoney);
I have tried all the suggestions. If the output value has zero as the 4th decimal its not displaying it. for ex, instead of 0.3070 it is displaying 0.307. If thh fourth decimal is other than zero, it works just fine.
example:
Input value: 0.511519926
Output: 0.5115
Input Value: 0.45895644
Output Value: 0.459
I took off cultural settings and still it didn't work.
I did this and it worked
ClassA.gridTable.Columns[17].DefaultCellStyle.Format = "#,0.0000";
Thanks all for your valuable inputs.

Formatting a double with decimals C#

Is it possible to format a double, so he doesn't chance the text 2140.76 to 214076 but instead letting it be 2140.76?
I can't use ',' for the decimal numbers, since the entire text file that I'm reading are numbers using '.' for separating the decimals, 10000 records, every day, so ...
EDIT:
double natMB = 0;
boolean check = double.TryParse(splitline[8], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out natMB);
if (check == false)
{
natMB = 0;
}
else
{
natMB = natMB * 1024;
}
double intMB = 0;
boolean check2 = double.TryParse(splitline[9], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out intMB);
if (check2==false)
{
intMB=0;
}
else
{
intMB = intMB * 1024;
}
The 0 value is necessary since I need to enter these values in an SQL statement, and they need to show up as 0, not as null.
Your question is not clear, Do you want to parse a double from a string with dot decimal separator ?
If yes try with this :
double.Parse("2140.76", CultureInfo.InvariantCulture)
You can use the invariant culture to format a number with a decimal period, regardless of your local culture settings:
string formatted = someDouble.ToString(CultureInfo.InvariantCulture);
Start reading here:
http://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.aspx
Basically, you create an NumberFormatInfo that you can customise to use with String.Format to use any format you want.
Is it possible to format a double so he doesn't chance the text 2140.76 to 214076 but instead
letting it be 2140.76?
Yes. Let me play ignorant - I have no idea how you can even ask that and have the poroblem given the extensive formatting methods.
I can't use ',' for the decimal numbers, since the entire text file that i'm reading are numbers
using '.' for separating the decimals, 10000 records, every day, so ...
So the problem likely is that you ahve a culture issue at hand and an ignorant developer on the other side. Ignorant because files exchagned should always be english formatted always, to avoid that.
Anyhow, basically:
* Change your culture info in the thread to english or
* Use english culture info for parsing and text generation.
Read the documentation for the methods you use -there areo verlaods that allow you to tune the formatting.

Categories