ASP.net ListBox currency formatting - c#

Ok guys, I have a ListBox which displays products (they are a custom class and have ID, name, price) that are in a binding list.. I want the ListBox to display the item name AND the price. The listbox (lbProductsChosen) has "DataTextField" set to the Name and DataValueField set to the ID. I am using the PreRender event to check each Item, look at its price from the binding list (blProducts) etc. and it works great. I get the name and price displayed in the list with this. However, when it is displayed, despite me formatting it using String.Format, the result is still a decimal number (ex. 3.20000) and it just looks ugly. Does anyone know why its working to display it, but not displaying it how I want it formatted.
protected void lbProductsChosen_PreRender(object sender, EventArgs e)
{
foreach (ListItem item in lbProductsChosen.Items)
{
string currentDescription = item.Text;
int convertedValue = Convert.ToInt32(item.Value);
for (int i = 0; i < blProducts.Count; i++)
{
if (blProducts[i].ProductID == convertedValue)
{
decimal ItemPrice = blProducts[i].Price;
string convertedPrice = ItemPrice.ToString();
string currentPrice = String.Format("{0:c}", convertedPrice);
string currentDescriptionPadded = currentDescription.PadRight(30);
item.Text = currentDescriptionPadded + currentPrice;
}
}
}
}

MSDN states the following about the String.Format method.
Generally, objects in the argument list are converted to their string representations by using the conventions of the current culture, which is returned by the CultureInfo.CurrentCulture property.
If you use the currency format specifier c it will use the currency format which is defined in the system settings. Take a look under control panel -> region -> additional settings -> currency. Maybe you have messed up settings there.
If you want to ignore the local settings which would make sense for currency you could do the following. (example in dollar with allways two decimal places)
decimal price = 12.10999999m;
String.Format("${0:0.00}", price);
$12.10
Be aware of that String.Format doesn't round the number correctly but just cuts it off.

Related

How to get the format string for a specified currency and culture

I have SSRS reports that display currency amounts. They need to be both culture aware and currency aware. Some reports show different currencies in the same table. I have no trouble with culture awareness. It's currency formatting that's the trouble. Importantly, when I export to Excel, the values in these currency fields must be sortable as numbers. That means the cell values must be numbers, so I cannot use the normal .ToString("C", culture) functions that so many other posts end up with. I need to keep the numeric value in the field and to apply .NET's format string to the number (e.g. "'$'#,0.00;('$'#,0.00)"). This way, Excel will treat the value as a number for sorting purposes but display the correctly formatted currency.
Is it possible to use code to modify a NumberFormatInfo instance and then somehow return the string value of the formatter, such as "'€'#,0.00;('€'#,0.00)"?
var numberFormat = new CultureInfo("en-US").NumberFormat;
numberFormat.CurrencySymbol = "€";
return numberFormat.GetCurrencyFormatString(); //this is an imaginary function that I need to return "'€'#,0.00;('€'#,0.00)"
I have tried programmatically setting the currency symbol based on the currency information of each row. As far as I know, SSRS does not allow me to use an Expression to set the currency symbol. It only offers a dropdown list.
My users don't like it when I show the currency code (e.g. USD, CAD), so I'm stuck with showing the symbol (e.g. $, CA$).
As far as I can tell, you'll need to manually construct this format string using the CultureInfo class.
Using the docs on CurrencyPositivePattern and CurrencyNegativePattern (see here and here), I've put together something that works but might need some tweaking:
string GetCurrencyFormat(CultureInfo culture)
{
//we'll use string.Format later to replace {0} with the currency symbol
//and {1} with the number format
string[] negativePatternStrings = { "({0}{1})", "-{0}{1}", "{0}-{1}", "{0}{1}-", "({1}{0})",
"-{1}{0}", "{1}-{0}", "{1}{0}-", "-{1} {0}", "-{0} {1}",
"{1} {0}-", "{0} {1}-", "{0} -{1}", "{1}- {0}", "({0} {1})",
"({1} {0})" };
string[] positivePatternStrings = { "{0}{1}", "{1}{0}", "{0} {1}", "{1}{0}" };
var numberFormat = culture.NumberFormat;
//Generate 0's to fill in the format after the decimal place
var decimalPlaces = new string('0', numberFormat.CurrencyDecimalDigits);
//concatenate the full number format, e.g. #,0.00
var fullDigitFormat = $"#{numberFormat.CurrencyGroupSeparator}0{numberFormat.CurrencyDecimalSeparator}{decimalPlaces}";
//use string.Format on the patterns to get the positive and
//negative formats
var positiveFormat = string.Format(positivePatternStrings[numberFormat.CurrencyPositivePattern],
numberFormat.CurrencySymbol, fullDigitFormat);
var negativeFormat = string.Format(negativePatternStrings[numberFormat.CurrencyNegativePattern],
numberFormat.CurrencySymbol, fullDigitFormat);
//finally, return the full format
return $"{positiveFormat};{negativeFormat}";
}
This returns $#,0.00;($#,0.00) for en-US, £#,0.00;-£#,0.00 for en-GB, for example.

DataGridView: How to allow comma and dot as a separators at the same time

I have a DataGridViewTextBoxColumn which is binded to a property. I want to allow user to input numbers no matter what he uses to separate decimals. Also I don't need spaces or commas to separate thousads.
It's simple:
1.908 = 1.908
1,908 = 1.908
And if there is no way to specify format string, can i Replace(",",".") before binding? Or any other way?
Thank you. (Sorry for my English)
Crete another property of String type which will be bounded to that column.
Then set/read value of original property through this
public class YourBindableItem
{
public decimal OriginalValue { get; set; }
public decimal ParsedValue
{
get { return this.OriginalValue.ToString(); }
set
{
string forParse =
value.Replace(",", Globalization.CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator);
decimal temp = 0;
if(decimal.TryParse(forParse,
out temp,
Globalization.CultureInfo.InvariantCulture) == true)
{
this.OriginalValue = temp;
}
//if value wasn't parsed succesfully, original value will be returned
this.RaiseOnPropertyChanged(nameOf(this.ParsedValue));
}
}
}
The DataGridView already formats according to the regional settings for the current user, at least if you data bind to an object data source and the property is numeric (i.e. not a string).
You can test this by opening Region and Language in Windows and switching between e.g. the English (United States) format and Swedish (Sweden). In the former case, the input 2.718 will parse correctly while in the second 2,718 will. You'll have to run without debugging in VS in order to load fresh settings.
(I would not suggest trying to parse both comma and dot as a decimal separator for the same user, if you're thinking of doing that. That's not the expected behavior for most users and it would lead to bugs if the user should happen to use the thousand separator too.)

Code not converting text

I have a textbox that allows users to input a decimal values that then gets stored in the a table in the database, this piece of code works in the development environment. I have now published the my project to the server and now is not longer taking the values with the decimal places.
decimal ReceiptAmount;
decimal AmountDue;
decimal Change;
if (!string.IsNullOrEmpty(((TextBox)dl_Item.FindControl("tb_ReceiptAmount")).Text))
{
if (((TextBox)dl_Item.FindControl("tb_ReceiptAmount")).Text.Contains(".") == true)
{
ReceiptAmount = Convert.ToDecimal(((TextBox)dl_Item.FindControl("tb_ReceiptAmount")).Text.Replace(".", ","));
}
else
{
ReceiptAmount = Convert.ToDecimal(((TextBox)dl_Item.FindControl("tb_ReceiptAmount")).Text);
}
}
else
{
ReceiptAmount = 0;
}
if (!string.IsNullOrEmpty(((TextBox)dl_Item.FindControl("tb_AmountDue")).Text))
{
if (((TextBox)dl_Item.FindControl("tb_AmountDue")).Text.Contains(".") == true)
{
AmountDue = Convert.ToDecimal(((TextBox)dl_Item.FindControl("tb_AmountDue")).Text.Replace(".", ","));
}
else
{
AmountDue = Convert.ToDecimal(((TextBox)dl_Item.FindControl("tb_AmountDue")).Text);
}
}
else
{
AmountDue = 0;
}
if (!string.IsNullOrEmpty(((TextBox)dl_Item.FindControl("tb_Change")).Text))
{
if (((TextBox)dl_Item.FindControl("tb_Change")).Text.Contains(".") == true)
{
Change = Convert.ToDecimal(((TextBox)dl_Item.FindControl("tb_Change")).Text.Replace(".", ","));
}
else
{
Change = Convert.ToDecimal(((TextBox)dl_Item.FindControl("tb_Change")).Text);
}
}
else
{
Change = 0;
}
I am not to sure what seems to be the problem with this piece of code. The Textbox are found in a datalist that I loop through to get all of the values.
The Convert.ToDecimal overload that takes a string as input will parse the string using the CultureInfo.CurrentCulture. Probably your server has different regional settings. Depending on regional settings, a comma or point may be either interpreted as a thousand separator (and thus ignored) or as the decimal separator.
Instead, you should use Decimal.Parse directly, providing either a specific culture or the invariant culture, depending on your use case.
Ideally, you'd set the culture of the user somewhere. To achieve this there are multiple approaches, e.g. for ASP.Net Web forms: https://msdn.microsoft.com/en-us/library/bz9tc508.aspx
If you parse the string using the correct culture, you can get rid of the string manipulation for replacing . with ,.
First of all, lines like
if (!string.IsNullOrEmpty(((TextBox)dl_Item.FindControl("tb_ReceiptAmount")).Text))
look very ugly; let's extract a method (copy/paste is very, very bad practice):
private String FindDLText(String controlName) {
var box = dl_Item.FindControl(controlName) as TextBox;
return box == null ? null : box.Text;
}
Then you don't need checking Text.Contains(".") == true, just Replace if you really need it:
private Decimal FindDLValue(String controlName) {
String text = FindDLText(controlName);
if (String.IsNullOrEmpty(text))
return 0.0M;
//TODO: check if you really need this
//text = text.Replace(".", ",");
// you have to specify Culture either InvariantCulture or some predefined one;
// say, new CultureInfo("ru-RU") // <- use Russian Culture to parse this
return Decimal.Parse(text, CultureInfo.InvariantCulture);
}
Finally, you can get
decimal ReceiptAmount = FindDLValue("tb_ReceiptAmount");
decimal AmountDue = FindDLValue("tb_AmountDue");
decimal Change = FindDLValue("tb_Change");
feel the difference: three evident lines and two simple methods.

Display floating points in f3 format in RDLC TABLIX

In my report, I have a tablix. Now I want to show the numeric data in f3 format. I have set text box property of the tablix column to number and with three decimal points.
Now when the data is e.g. 12.120 then it shows me 12.12 instead of 12.120.
And I want to show when the data is like 12 to 12.000.
How to do it?
double d = 12.20;
Console.WriteLine(d.ToString("0.000", new CultureInfo("en-US", false)));
First off, here's your reference material.
You can use those format strings, or the placeholder style.
Examples:
Double value = 12.20D;
String str1 = String.Format("{0:F3}", value);
String str2 = value.ToString("F3");
String str3 = value.ToString("0.000");
To make this work with your TextBox, however, you will need to pass the entered values through a routine that applies said formatting.
Using the TextBox's Validated method is a good choice because it is fired after editing is complete, and not while the user is still typing (like TextChanged would):
private void textBox1_Validated(Object sender, EventArgs e)
{
Double dbl;
if (!String.IsNullOrWhiteSpace(textBox1.Text) &&
Double.TryParse(textBox1.Text, out dbl))
{
//Replace with your formatting of choice...
textBox1.Text = String.Format("{0:F3}", dbl);
}
}
You have to set TextBox.Format property to f3.

C# Converting a Currency String to Double

I have a basic understanding of C# and the .NET Framework, I have been given an assignment to build a POS (Point Of Sales) screen, I have currently hit a small brick wall trying to convert a currency related string back to a double.
I have two list boxes and several product buttons on the screen, the buttons are populated using a library class provided to us (essentially showing we can work with components)
One list box holds the product name while the other holds the price of that product, when a product button is selected it takes the product name from the buttons text and within its tag there is the price which is added to the list box of prices.
my problem is I want to show the prices in the List Box as a currency also that it shows all '0' I can do this no problem by doing either the following
value.ToString("C");
string.Format("{0:C}",value);
or using Convert etc.
Although because I have done this if I want to remove an item from the list by double clicking I need to take away the price from the total so I need to convert to back to double although because its in its current format I get an error when trying to perform that action I have looked around and I cannot seem to find anyway around it, the only option I can see is just leaving the string value as it is and not convert it to a currency format.
the ERROR: {"Input string was not in a correct format."}
Code Snippet
private void panelBtns_Click(object sender, EventArgs e)
{
Button panelBtn = (Button)sender;
lstProduct.Items.Add(panelBtn.Text);
double price = Convert.ToDouble(panelBtn.Tag);
>>CURRENCY FORMAT>> lstPrice.Items.Add(string.Format("{0:C}",price));
dblTotal = dblTotal + Convert.ToDouble(panelBtn.Tag);
lblTotal.Text = string.Format("{0:C}", dblTotal);
lblOutput.Text = "0";
lblOutput.Tag = "0";
}//End Panel Buttons
private void lstProduct_DoubleClick(object sender, EventArgs e)
{
int index = lstProduct.SelectedIndex;
lstPrice.SelectedIndex = lstProduct.SelectedIndex ;
>> ERROR HERE >> double price = Convert.ToDouble(lstPrice.GetItemText(lstPrice.SelectedItem));
dblTotal = dblTotal - price;
lstProduct.Items.RemoveAt(index);
lstPrice.Items.RemoveAt(index);
lblTotal.Text = string.Format("{0:C}", dblTotal);
}
Would anyone have any idea how I could possibly fix this, I had though about creating an invisible list to store the actual value of the tag so I can use that for later but would there be any other methods?
NOTE: I am also aware that using double for currency is not a very reliable
The easiest way to parse the C format is probably with
Double.Parse(text, System.Globalization.NumberStyles.Currency)
Of course you would always want to use Decimal to handle currency, and Decimal.Parse takes the same parameters.
In this case, though, you would want to store your internal numeric values along with their textual representation rather than converting to a string and then parsing back into a number.
other way, but please note, that you must try all cultures if removing symbol gives just decimal string, use Gabe's answer (posted just before mine :D)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Threading;
namespace ConsoleApplication6
{
class Program
{
static void Main(string[] args)
{
//US-en culture / default I'm developing on
string currencyString = "$12.99"; //assuming got from: lstPrice.GetItemText(lstPrice.SelectedItem);
CultureInfo ci = Thread.CurrentThread.CurrentUICulture;
double d = Convert.ToDouble(currencyString.Replace(ci.NumberFormat.CurrencySymbol, ""));
//using custom culture
currencyString = "12.99zł";
ci = CultureInfo.GetCultureInfo("PL-pl");
d = Convert.ToDouble(currencyString.Replace(ci.NumberFormat.CurrencySymbol, ""));
}
}
}
You may want to look at assigning the decimal too with Math.Round Method
https://msdn.microsoft.com/en-us/library/system.math.round(v=vs.110).aspx

Categories