.NET MAUI动态绑定小数位数的DecimalDigitsBehavior失效求助
.NET MAUI DecimalDigitsBehavior绑定ViewModel属性失效问题解决
问题分析
你遇到的核心问题是:DecimalDigitsBehavior的MaxDecimalDigits绑定到ViewModel的ObservableProperty时,ViewModel属性更新后,行为仍沿用初始化时的默认值2。原因是自定义行为的可绑定属性未实现属性变更回调,导致属性值更新后,相关的校验、格式化逻辑未同步更新。
修复方案
1. 修改可绑定属性定义,添加变更回调
在DecimalDigitsBehavior中,为MaxDecimalDigitsProperty添加属性变更回调,确保值变化时同步更新Entry的校验规则和文本格式:
using System.Text.RegularExpressions; namespace MCoreMatter.Behaviors { public class DecimalDigitsBehavior : Behavior<Entry> { public static readonly BindableProperty MaxDecimalDigitsProperty = BindableProperty.Create( nameof(MaxDecimalDigits), typeof(int), typeof(DecimalDigitsBehavior), 2, propertyChanged: OnMaxDecimalDigitsChanged); // 新增属性变更回调 public int MaxDecimalDigits { get => (int)GetValue(MaxDecimalDigitsProperty); set => SetValue(MaxDecimalDigitsProperty, value); } // 属性变更时触发的回调方法 private static void OnMaxDecimalDigitsChanged(BindableObject bindable, object oldValue, object newValue) { if (bindable is DecimalDigitsBehavior behavior && behavior.AssociatedObject is Entry entry) { // 重新校验并格式化当前文本,适配新的小数位数 behavior.ValidateAndFormatEntryText(entry); } } // 通用校验格式化方法,统一处理文本规则 private void ValidateAndFormatEntryText(Entry entry) { if (string.IsNullOrEmpty(entry.Text)) { entry.Text = string.Format("{0:0." + new string('0', MaxDecimalDigits) + "}", 0); return; } // 校验文本是否符合新规则,不符合则截断修正 string pattern = $@"^-?\d*(\.\d{{0,{MaxDecimalDigits}}})?$"; if (!Regex.IsMatch(entry.Text, pattern)) { var parts = entry.Text.Split('.'); entry.Text = parts.Length > 1 ? $"{parts[0]}.{parts[1].Substring(0, Math.Min(parts[1].Length, MaxDecimalDigits))}" : parts[0]; } // 统一格式化文本 string text = entry.Text.TrimEnd('.'); entry.Text = double.TryParse(text, out double value) ? string.Format("{0:0." + new string('0', MaxDecimalDigits) + "}", value) : string.Format("{0:0." + new string('0', MaxDecimalDigits) + "}", 0); } protected override void OnAttachedTo(Entry entry) { entry.TextChanged += OnEntryTextChanged; entry.Unfocused += OnEntryUnfocused; base.OnAttachedTo(entry); } protected override void OnDetachingFrom(Entry entry) { entry.TextChanged -= OnEntryTextChanged; entry.Unfocused -= OnEntryUnfocused; base.OnDetachingFrom(entry); } private void OnEntryTextChanged(object sender, TextChangedEventArgs args) { if (sender is Entry entry) { string pattern = $@"^-?\d*(\.\d{{0,{MaxDecimalDigits}}})?$"; var isValid = Regex.IsMatch(args.NewTextValue, pattern); if (!isValid) { entry.Text = args.OldTextValue; entry.CursorPosition = entry.Text.Length; } } } private void OnEntryUnfocused(object sender, EventArgs args) { if (sender is Entry entry) { ValidateAndFormatEntryText(entry); } } } }
2. 确认绑定上下文正确性
确保XAML中绑定路径正确,且页面的BindingContext已正确设置为目标ViewModel:
<Entry Placeholder="0.0" Keyboard="Numeric" Text="{Binding My_Unit}"> <Entry.Behaviors> <behaviors:DecimalDigitsBehavior MaxDecimalDigits="{Binding MaxUnitDecimalDigits}" /> </Entry.Behaviors> </Entry>
验证效果
当ViewModel的MaxUnitDecimalDigits在ApplyQueryAttributes中被赋值为1或0时:
- 行为会立即感知到属性变更,自动重新校验并格式化Entry的现有文本
- 后续输入文本时,会使用更新后的小数位数规则进行实时校验
内容的提问来源于stack exchange,提问作者Bryan Tan
相关产品推荐
相关产品推荐

