You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin.Forms ObservableCollection存储decimal值丢失逗号数值异常问题

Xamarin.Forms ObservableCollection存储decimal价格出现100倍偏差排查方案

ObservableCollection<T>本身不会主动修改存入元素的属性值,其核心存储逻辑和List<T>一致,都是保存对象引用,唯一区别是额外实现了集合变更通知。出现1.50被存为150的问题,按以下步骤定位即可:

  • 第一步:断点定位偏差出现的准确节点
    在ObCoVociDocumento.Add(vd)代码行前后加断点验证:
    1. Add执行前,直接查看新建的vd对象中Prezzo属性的运行时值
    2. Add执行后,立刻读取ObCoVociDocumento.Last().Prezzo的值
    • 如果Add执行前值已经是150:问题出在上游价格计算或原始值读取逻辑,和集合类型无关
    • 如果Add前值为1.50,Add执行后立刻变为150:直接检查ObCoVociDocumento.CollectionChanged事件绑定的所有处理方法,其中一定存在修改元素Prezzo属性的逻辑(比如货币单位转换、系数计算等)。换用List<T>时正常,就是因为List没有集合变更通知事件,不会触发你写的这段变更处理代码。
    • 如果Add后立即查询值仍为1.50,只有遍历计算总金额时才变为150:检查遍历求和的逻辑中是否存在隐式类型转换、字符串格式化后反序列化的错误操作。
  • 第二步:排查价格计算逻辑的类型转换问题
    你当前的价格计算代码存在隐式类型转换风险:
    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 20:09:11