问题
How to show a numeric (currency) value in WPF so that the currency symbol would not come from the user's regional settings, locale or anything but from the property of the binded object.
For example in DataGrid I would have Item objects:
<DataGrid Grid.Row="1" ItemsSource="{Binding Items}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding SomeNumber, StringFormat=c}" />
</DataGrid.Columns>
</DataGrid>
public Item()
{
public double SomeNumber { get; set; }
public string CurrencySymbol { get; set; }
}
The above standard "c"formatting will show currency symbol based on some user setting and ignoring the business object.
But the value should be displayed like this
SomeNumber = 3456234.67 (positive numbers)
CurrencySymbol ="€" > €3 456 234.67
CurrencySymbol ="$" > $3 456 234.67
CurrencySymbol ="₽" > ₽3 456 234.67
SomeNumber = -3456234.67 (negative numbers)
CurrencySymbol ="€" > (€3 456 234.67)
CurrencySymbol ="$" > ($3 456 234.67)
CurrencySymbol ="₽" > (₽3 456 234.67)
SomeNumber= 0 (zero values)
CurrencySymbol ="€" > -
CurrencySymbol ="$" > -
CurrencySymbol ="₽" > -
Is there a way to get the currency symbol to the value this way with StringFormat?
回答1:
The correct way to automatically attach the currency symbol to a number using StringFormat is by using a ConverterCulture:
<!-- This will be shown as '¥1,423.7' -->
<DataGridTextColumn Header="Amount"
Binding="{Binding Path=SomeNumber,
StringFormat=c,
ConverterCulture='ja-JP'}"/>
<!-- This will be shown as '1.423.70 €' -->
<DataGridTextColumn Header="Amount"
Binding="{Binding Path=SomeNumber,
StringFormat=c,
ConverterCulture='de-DE'}"/>
The good thing about it is that the number is also formatted according to requested ConverterCulture.
In your case you want to format the number yourself (notice the position of the currency symbol is changing according to the ConverterCulture as well), also, you want to decide what will be the currency displayed yourself, which makes it impossible to relay on the ConverterCulture.
In this case, the correct way to do it will be creating an IValueConverter yourself:
public class CurrencyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Item valueAsItem = value as Item;
if (valueAsItem != null)
{
double amount = valueAsItem.SomeNumber;
if (amount == 0)
{
return "-"; //In the question this is the display for 0.
}
if (amount < 0)
{
amount *= -1; //In the question the numbers always display positive.
}
//In the question this is the format for the numbers.
return valueAsItem.CurrencySymbol + amount.ToString("### ### ###.###");
}
return string.Empty;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
And in the .xaml:
Inside the
WindowAttribute:<Window.Resources> <local:CurrencyConverter x:Key="CurrencyConverter" /> </Window.Resources>And for the
DataGrid:<DataGrid ItemsSource="{Binding MyItems}" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Header="Amount" Binding="{Binding Converter={StaticResource CurrencyConverter}}"/> </DataGrid.Columns> </DataGrid>
Now when the DataContext is as the following:
public class MyDataContext
{
public ICollectionView MyItems { get; set; }
public MyDataContext()
{
List<Item> items = new List<Item>
{
new Item { CurrencySymbol = "$", SomeNumber = 123.4 },
new Item { CurrencySymbol = "₹", SomeNumber = 0 },
new Item { CurrencySymbol = "₹", SomeNumber = -14345623.7 }
};
MyItems = CollectionViewSource.GetDefaultView(items);
}
}
public class Item
{
public double SomeNumber { get; set; }
public string CurrencySymbol { get; set; }
}
The grid looks like that:
as requested.
More info on double formatting on MSDN.
来源:https://stackoverflow.com/questions/34237911/currency-symbol-in-numeric-value-based-on-object-property-in-xaml