Xamarin.Forms ObservableCollection存储decimal值丢失逗号数值异常问题
Xamarin.Forms ObservableCollection存储decimal价格出现100倍偏差排查方案
ObservableCollection<T>本身不会主动修改存入元素的属性值,其核心存储逻辑和List<T>一致,都是保存对象引用,唯一区别是额外实现了集合变更通知。出现1.50被存为150的问题,按以下步骤定位即可:
- 第一步:断点定位偏差出现的准确节点
在ObCoVociDocumento.Add(vd)代码行前后加断点验证:- Add执行前,直接查看新建的
vd对象中Prezzo属性的运行时值 - Add执行后,立刻读取
ObCoVociDocumento.Last().Prezzo的值
- 如果Add执行前值已经是150:问题出在上游价格计算或原始值读取逻辑,和集合类型无关
- 如果Add前值为1.50,Add执行后立刻变为150:直接检查
ObCoVociDocumento.CollectionChanged事件绑定的所有处理方法,其中一定存在修改元素Prezzo属性的逻辑(比如货币单位转换、系数计算等)。换用List<T>时正常,就是因为List没有集合变更通知事件,不会触发你写的这段变更处理代码。 - 如果Add后立即查询值仍为1.50,只有遍历计算总金额时才变为150:检查遍历求和的逻辑中是否存在隐式类型转换、字符串格式化后反序列化的错误操作。
- Add执行前,直接查看新建的
- 第二步:排查价格计算逻辑的类型转换问题
你当前的价格计算代码存在隐式类型转换风险:
如果vd.Prezzo = Convert.ToDecimal(SelectedProdotto.Prezzo + (SelectedProdotto.Prezzo / 100 * SelectedProdotto.ScontoA));SelectedProdotto.Prezzo、ScontoA是整数类型,C#的整数除法会直接舍弃小数位,极易出现计算偏差。同时要确认SelectedProdotto.Prezzo的存储单位:不少业务系统会将货币值乘100存为整数(以分为单位)避免浮点精度问题,如果原始值是150(对应1.50元),直接计算自然会得到错误结果。
建议改为显式decimal类型运算,避免隐式转换坑:decimal prezzoBase = Convert.ToDecimal(SelectedProdotto.Prezzo); decimal scontoPercentuale = Convert.ToDecimal(SelectedProdotto.ScontoA); // 100m表示decimal类型的100,强制整个表达式按decimal精度计算 vd.Prezzo = prezzoBase + (prezzoBase / 100m * scontoPercentuale); - 第三步:排查实体属性和UI绑定的转换逻辑
你贴出的VoceDocumento实体类代码不完整,先检查Prezzo属性的set访问器中是否写了额外的值转换逻辑(比如自动乘100适配SQLite整数存储);如果是UI上显示值为150,还要检查XAML绑定是否用了错误的值转换器、StringFormat是否和当前线程区域文化匹配——比如意大利区域文化中逗号是小数点分隔符,如果设备线程文化被切为英文区域,逗号会被识别成千分位,"1,50"转decimal就会得到150。绑定货币值时建议显式指定区域文化:<Label Text="{Binding Prezzo, StringFormat='{0:C}', ConverterCulture='it-IT'}"/>
内容的提问来源于stack exchange,提问作者Fabrizio La Racca
相关产品推荐
相关产品推荐

