如何在Xamarin.Forms中实现折扣百分比与金额文本框的双向联动计算
问题根源
当前的死循环问题来自两个设计缺陷:
- 计算逻辑中同时对
Discount和Percent两个变量赋值,修改任意一个变量都会触发另一个的变更事件,循环调用计算逻辑 TextChanged事件每输入一个字符就触发,用户还未完成输入就会触发计算,容易出现异常值
修复方案
第一步:修改C#逻辑,区分计算触发来源
给计算方法增加触发来源标识,只对非用户手动修改的字段进行赋值,同时增加防重入标记和除0保护:
PercentChangedCommand = new Xamarin.Forms.Command(() => CalculateData(isPercentChanged: true)); DiscountChangedCommand = new Xamarin.Forms.Command(() => CalculateData(isPercentChanged: false)); // 防重入标记,避免极端情况递归调用 private bool _isCalculating = false; private void CalculateData(bool isPercentChanged) { if (_isCalculating) return; _isCalculating = true; try { SubTotal = amount + Price1 + Price2; // 增加小计为0的保护,避免除以0报错 if (SubTotal <= 0) { Discount = 0; Percent = 0; } else { if (isPercentChanged) { // 用户修改了百分比,仅计算折扣金额 Discount = SubTotal * (Percent / 100); } else { // 用户修改了折扣金额,仅计算百分比,保留0位小数匹配XAML格式 Percent = Math.Round(Discount / SubTotal * 100, 0); } } GST = SubTotal * 0.07; TotalAmount = SubTotal - Discount + GST; } finally { _isCalculating = false; } }
第二步(可选,优化输入体验):修改XAML触发时机
如果不需要每输入一个字符就实时计算,可以把触发事件从TextChanged改为Unfocused,等用户完成输入离开输入框时再计算,避免输入过程中数值被改写:
<Grid Grid.Row="4" ColumnDefinitions="0.7*,1*"> <Frame Grid.Column="0" Style="{StaticResource FrameStyleBlack2}"> <OnPlatform x:TypeArguments="View"> <OnPlatform.Android> <customstyle:EntryBorderless Keyboard="Numeric" Style="{StaticResource EntryStyle2}" Text="{Binding Percent, StringFormat='{0:F0}'}"> <customstyle:EntryBorderless.Behaviors> <xct:EventToCommandBehavior Command="{Binding PercentChangedCommand}" EventName="Unfocused"/> </customstyle:EntryBorderless.Behaviors> </customstyle:EntryBorderless> </OnPlatform.Android> </OnPlatform> </Frame> <Frame Grid.Column="1" Style="{StaticResource FrameStyleBlack2}"> <OnPlatform x:TypeArguments="View"> <OnPlatform.Android> <customstyle:EntryBorderless Keyboard="Numeric" Style="{StaticResource EntryStyle2}" Text="{Binding Discount, StringFormat='{0:F2}'}"> <customstyle:EntryBorderless.Behaviors> <xct:EventToCommandBehavior Command="{Binding DiscountChangedCommand}" EventName="Unfocused"/> </customstyle:EntryBorderless.Behaviors> </customstyle:EntryBorderless> </OnPlatform.Android> </OnPlatform> </Frame> </Grid>
说明
如果需要实时计算,无需修改XAML的触发事件,仅修改C#逻辑即可解决死循环问题。
内容的提问来源于stack exchange,提问作者Kai
相关产品推荐
相关产品推荐

