在wpf xaml中格式化为货币且不带尾随零 [英] Format as currency with no trailing zeroes in wpf xaml

查看:215
本文介绍了在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:

  1. 利用C#的

a.考虑负值(例如-1 --> ($1))

a. Consider negative values (e.g. -1 --> ($1))

b.迎合当前不同的语言环境/文化

b. Cater varying current locale/culture

绑定到多种数据类型(decimaldoubleint等).

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;
}


有关更多信息ToCurrency这里


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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆