假设我们有一个viewmodel属性MyMoney
。如何在xaml视图中将其格式化为没有尾随零的货币?
例如:
MyMoney = 1; //$1
MyMoney = 1.2 //$1.2
我已经在xaml中尝试了以下操作(例如<TextBox Text="{Binding MyMoney, StringFormat=..."/>
),但它不满足所有条件:
StringFormat=C
显示货币,但尾随零。
StringFormat=C0
显示货币,但仅显示整数。
StringFormat={}{0:0.##}
不显示尾随零,但不显示货币。
StringFormat={}{0:$0.##}
不显示尾随零,而是硬编码的$
。我们应该能够满足当前语言环境/文化的货币要求。
答案 0 :(得分:2)
我认为您非常需要在此处使用转换器,因为需要删除尾随零。 这可能需要更多的工作,但是:
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Markup;
namespace wpf_99
{
public class CurrencyFormatConverter : MarkupExtension, IValueConverter
{
// public double Multiplier { get; set; } You could pass parameters to properties.
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return CultureInfo.CurrentCulture.NumberFormat.CurrencySymbol + System.Convert.ToDecimal(value).ToString("0.##");
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string input = value.ToString();
if(!char.IsDigit(input[0]))
{
input= input.Substring(1);
}
if(input.Length == 0)
{
return 0;
}
return Decimal.Parse(input);
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
}
}
用法
<TextBox Text="{Binding Money,UpdateSourceTrigger=PropertyChanged, Converter={local:CurrencyFormatConverter}}"/>
答案 1 :(得分:0)
可能您会知道字符串格式的“ C”是根据本地计算机上的语言环境/区域性设置起作用的。但是,回答您的问题,我建议将尾随零的删除代码放在属性级别并保持在xaml级别上的字符串格式应尽可能简单。例如
在xaml级别:
<TextBox x:Name="TextBox_Curr" Height="50" Text="{Binding Money,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay,StringFormat={}{0:C}}" Margin="120,134,156,135"/>
在模型级别(仅原始代码):
private decimal _money;
public decimal Money
{
get { return _money; }
set {
_money = value;
_money.ToString("0.##");
NotifyPropertyChanged("Money"); }
}
它在运行示例代码时对我有用。
此外,如果您不想更改系统设置,则可以选择强制区域性设置。
public static class Cultures
{
public static readonly CultureInfo UnitedKingdom =
CultureInfo.GetCultureInfo("en-GB");
}
Then:
Money.ToString("C", Cultures.UnitedKingdom)
答案 2 :(得分:0)
首先,我想感谢@Andy的his answer,这使我使用了IValueConverter
。
我发布的解决方案具有以下优点:
利用C#的"C" format specifier
a。考虑负值(例如-1 --> ($1)
)
b。适应当前不同的语言环境/文化
绑定到多种数据类型(decimal
,double
,int
等)。
返回DependencyProperty.UnsetValue
when ConvertBack
is unable to produce a value。
以上所有内容均遵循StringFormat=c
在wpf中的行为方式(例如,在TextBox
中的行为),只是转换器会根据需要删除尾随零。
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;
}
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));
}