如何让NumberBox显示并返回Decimal值?绑定DecimalFormatter报错求解
NumberBox绑定DecimalFormatter抛出异常的解决方法
问题场景
在ListView中使用NumberBox,绑定集合内的Decimal类型属性,要求UI以Decimal格式显示值,且返回值为Decimal而非Double。在ViewModel中初始化DecimalFormatter并绑定到NumberBox的NumberFormatter属性时,抛出异常:Failed to assign the property Microsoft.UI.Xaml.Controls.NumberBox.NumberFormatter。
相关代码:
XAML代码
<NumberBox x:Name="nbFeedCost" Grid.Column="30" IsWrapEnabled="true" NumberFormatter="{Binding DataContext.Formatter, ElementName=ngLot}" Style="{StaticResource NumberBoxRightAlignStyle}" Value="{Binding FeedCost, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
ViewModel代码
DecimalFormatter Formatter = new DecimalFormatter();
原因分析
NumberBox.NumberFormatter属性要求的是INumberFormatter2接口类型,而DecimalFormatter属于Windows.Globalization.NumberFormatting命名空间,它实现的是INumberFormatter和INumberParser,并不兼容INumberFormatter2,直接绑定会导致类型不匹配的异常。
解决方案
方法1:自定义兼容的格式化器
实现一个继承INumberFormatter2的类,内部用DecimalFormatter处理格式化逻辑:
using Windows.Globalization.NumberFormatting; public class NumberBoxDecimalFormatter : INumberFormatter2 { private readonly DecimalFormatter _decimalFormatter; public NumberBoxDecimalFormatter() { _decimalFormatter = new DecimalFormatter(); // 可按需设置小数位数等格式 _decimalFormatter.FractionDigits = 2; } public string FormatDouble(double value) { return _decimalFormatter.Format((decimal)value); } public string FormatInt(long value) { return _decimalFormatter.Format((decimal)value); } public string FormatUInt(ulong value) { return _decimalFormatter.Format((decimal)value); } public string FormatDecimal(decimal value) { return _decimalFormatter.Format(value); } }
然后在ViewModel中初始化这个自定义格式化器:
public INumberFormatter2 Formatter { get; } = new NumberBoxDecimalFormatter();
方法2:用值转换器+内置格式属性
如果不需要复杂区域化格式,可放弃绑定NumberFormatter,改用值转换器处理Decimal与Double的类型转换,同时用NumberBox的内置属性控制显示格式:
- 实现值转换器:
public class DecimalToDoubleConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { return value is decimal decimalValue ? (double)decimalValue : 0.0; } public object ConvertBack(object value, Type targetType, object parameter, string language) { return value is double doubleValue ? (decimal)doubleValue : 0m; } }
- 在XAML中引用并绑定:
<Page.Resources> <local:DecimalToDoubleConverter x:Key="DecimalToDoubleConverter" /> </Page.Resources> <NumberBox x:Name="nbFeedCost" Grid.Column="30" IsWrapEnabled="true" MinimumNumberDigits="2" MaximumNumberDigits="2" Style="{StaticResource NumberBoxRightAlignStyle}" Value="{Binding FeedCost, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource DecimalToDoubleConverter}}" />
关键注意点
NumberBox的Value属性默认是double类型,双向绑定Decimal类型必须使用值转换器,否则会出现绑定错误。- 自定义格式化器必须实现
INumberFormatter2接口,确保与NumberBox的属性类型兼容。
内容的提问来源于stack exchange,提问作者SANJEEV PRATAP Singh
相关产品推荐
相关产品推荐

