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

.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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 14:49:49