在wpf xaml中格式化为货币且不带尾随零 [英] Format as currency with no trailing zeroes in wpf xaml
问题描述
假设我们有一个viewmodel属性MyMoney
.如何在xaml视图中将其格式化为没有尾随零的货币?
Assuming we have a viewmodel property MyMoney
. How can I format it in its view xaml as a currency with no trailing zeroes?
例如:
MyMoney = 1; //$1
MyMoney = 1.2 //$1.2
我已经在xaml中尝试了以下操作(例如<TextBox Text="{Binding MyMoney, StringFormat=..."/>
),但是它不满足所有条件:
I've tried the following in xaml (e.g. <TextBox Text="{Binding MyMoney, StringFormat=..."/>
) but it doesn't satisfy all the conditions:
StringFormat=C
显示货币,但也显示尾随零.
StringFormat=C0
显示货币,但仅显示整数.
StringFormat={}{0:0.##}
不显示尾随零,但不显示为货币.
StringFormat={}{0:$0.##}
不显示尾随零,而是硬编码的$
.我们应该能够满足当前语言环境/文化的货币要求.
StringFormat=C
shows currency but also trailing zeroes.
StringFormat=C0
shows currency but shows only the whole number.
StringFormat={}{0:0.##}
does not show trailing zeroes but not as currency.
StringFormat={}{0:$0.##}
does not show trailing zeroes but hard-coded $
. We should be able to cater current locale/culture's currency.
推荐答案
首先,我要感谢@Andy的答案,导致我使用IValueConverter
.
First, I would like to give credit to @Andy for his answer which led me to use IValueConverter
.
我正在发布我的解决方案,它具有以下优点:
I'm posting my solution which offers the following benefits:
a.考虑负值(例如-1 --> ($1)
)
a. Consider negative values (e.g. -1 --> ($1)
)
b.迎合当前不同的语言环境/文化
b. Cater varying current locale/culture
绑定到多种数据类型(decimal
,double
,int
等).
Bind to multiple data types (decimal
, double
, int
, etc).
返回 DependencyProperty.UnsetValue
,当ConvertBack
无法产生值时.
Return DependencyProperty.UnsetValue
when ConvertBack
is unable to produce a value.
以上所有内容均遵循StringFormat=c
在wpf中的行为方式(例如在TextBox
中),但转换器会根据需要删除尾随零.
All of the above follow how StringFormat=c
will behave in wpf (e.g. in a TextBox
) except the converter removes trailing zeroes as desired.
public class CurrencyFormatConverter : MarkupExtension, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) =>
System.Convert.ToDecimal(value).ToCurrency(culture);
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
switch (Type.GetTypeCode(targetType))
{
case TypeCode.Decimal:
return Decimal.TryParse(value.ToString(), NumberStyles.Currency, culture, out var @decimal)
? @decimal
: DependencyProperty.UnsetValue;
case TypeCode.Double:
return Double.TryParse(value.ToString(), NumberStyles.Currency, culture, out var @double)
? @double
: DependencyProperty.UnsetValue;
case TypeCode.Int16:
return Int16.TryParse(value.ToString(), NumberStyles.Currency, culture, out var int16)
? int16
: DependencyProperty.UnsetValue;
case TypeCode.Int32:
return Int32.TryParse(value.ToString(), NumberStyles.Currency, culture, out var int32)
? int32
: DependencyProperty.UnsetValue;
case TypeCode.Int64:
return Int64.TryParse(value.ToString(), NumberStyles.Currency, culture, out var int64)
? int64
: DependencyProperty.UnsetValue;
case TypeCode.Single:
return Single.TryParse(value.ToString(), NumberStyles.Currency, culture, out var single)
? single
: DependencyProperty.UnsetValue;
case TypeCode.UInt16:
return UInt16.TryParse(value.ToString(), NumberStyles.Currency, culture, out var uint16)
? uint16
: DependencyProperty.UnsetValue;
case TypeCode.UInt32:
return UInt32.TryParse(value.ToString(), NumberStyles.Currency, culture, out var uint32)
? uint32
: DependencyProperty.UnsetValue;
case TypeCode.UInt64:
return UInt64.TryParse(value.ToString(), NumberStyles.Currency, culture, out var uint64)
? uint64
: DependencyProperty.UnsetValue;
default:
throw new NotSupportedException($"Converting currency string to target type {targetType} is not supported.");
}
}
public override object ProvideValue(IServiceProvider serviceProvider) => this;
}
More info on ToCurrency
here
public static class DecimalExtensions
{
/// <summary>
/// Converts a numeric value to its equivalent currency string representation using the specified culture-specific format information.
/// </summary>
/// <param name="value">The value to be converted.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <returns>The currency string representation of the value as specified by <paramref name="provider" />.</returns>
public static string ToCurrency(this decimal value, IFormatProvider provider) =>
/// Use "1" (or "-1" if value is negative)
/// as a placeholder for the actual value.
(value < 0 ? -1 : 1)
/// Format as a currency using the "C" format specifier.
.ToString("C0", provider)
/// Convert the absolute value to its string representation
/// then replace the placeholder "1".
/// We used absolute value since the negative sign
/// is already converted to its string representation
/// using the "C" format specifier.
.Replace("1", Math.Abs(value).ToString("#,0.############################", provider));
}
这篇关于在wpf xaml中格式化为货币且不带尾随零的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!