Blazor 自定义可重用基础组件之 限制输入值大小的NumberBox(InputNumber)

19 篇文章 1 订阅

我们可能限制用户输入值范围,超出视为无效且引发错误,这就是设置最大值和最小值。NumberBox.razor在这里未作改动。

NumberBox.razor.cs 代码:

    public partial class NumberBox<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TValue> : InputBase<TValue>
    {
        [Parameter]
        public required string Lable { get; set; }

        [Parameter]
        public string InputWidth { get; set; } = "300";

        [Parameter]
        public bool Disabled { get; set; }
        [Parameter]
        public int? Max { get; set; }
        [Parameter]
        public int? Min { get; set; }

        protected override void OnParametersSet()
        {
            base.OnParametersSet();
            Lable += ":";
            InputWidth += "px;";
            Dictionary<string, object> keyValues = new();
            if (Max.HasValue)
            {
                keyValues.Add("max", Max);
            }
            if (Min.HasValue)
            {
                keyValues.Add("min", Min);
            }
            AdditionalAttributes = keyValues;
        }

        //以下是复制于InputNumber 的源码,除了渲染部分注释掉外未作改动。
        private static readonly string _stepAttributeValue = GetStepAttributeValue();
        private static string GetStepAttributeValue()
        {

            // Unwrap Nullable<T>, because InputBase already deals with the Nullable aspect
            // of it for us. We will only get asked to parse the T for nonempty inputs.
            var targetType = Nullable.GetUnderlyingType(typeof(TValue)) ?? typeof(TValue);
            if (targetType == typeof(int) ||
                targetType == typeof(long) ||
                targetType == typeof(short) ||
                targetType == typeof(float) ||
                targetType == typeof(double) ||
                targetType == typeof(decimal))
            {
                return "any";
            }
            else
            {
                throw new InvalidOperationException($"The type '{targetType}' is not a supported numeric type.");
            }
        }

        /// <summary>
        /// Gets or sets the error message used when displaying an a parsing error.
        /// </summary>
        [Parameter] public string ParsingErrorMessage { get; set; } = "The {0} field must be a number.";

        /// <summary>
        /// Gets or sets the associated <see cref="ElementReference"/>.
        /// <para>
        /// May be <see langword="null"/> if accessed before the component is rendered.
        /// </para>
        /// </summary>
        [DisallowNull] public ElementReference? Element { get; protected set; }

        //这里是生成渲染树,我们用NumberBox.razor代替了。
        /// <inheritdoc />
        //protected override void BuildRenderTree(RenderTreeBuilder builder)
        //{
        //    builder.OpenElement(0, "input");
        //    builder.AddAttribute(1, "step", _stepAttributeValue);
        //    builder.AddMultipleAttributes(2, AdditionalAttributes);
        //    builder.AddAttribute(3, "type", "number");
        //    builder.AddAttributeIfNotNullOrEmpty(4, "name", NameAttributeValue);
        //    builder.AddAttributeIfNotNullOrEmpty(5, "class", CssClass);
        //    builder.AddAttribute(6, "value", CurrentValueAsString);
        //    builder.AddAttribute(7, "onchange", EventCallback.Factory.CreateBinder<string?>(this, __value => CurrentValueAsString = __value, CurrentValueAsString));
        //    builder.SetUpdatesAttributeName("value");
        //    builder.AddElementReferenceCapture(8, __inputReference => Element = __inputReference);
        //    builder.CloseElement();
        //}

        /// <inheritdoc />
        protected override bool TryParseValueFromString(string? value, [MaybeNullWhen(false)] out TValue result, [NotNullWhen(false)] out string? validationErrorMessage)
        {
            if (BindConverter.TryConvertTo<TValue>(value, CultureInfo.InvariantCulture, out result))
            {
                if (Max.HasValue && value != null)
                {
                    if (int.Parse(value) > Max)
                    {
                        validationErrorMessage = "数字最大为" + Max + "!";
                        return false;
                    }
                }
                if (Min.HasValue && value != null)
                {
                    if (int.Parse(value) < Min)
                    {
                        validationErrorMessage = "数字最小为" + Min + "!";
                        return false;
                    }
                }
                validationErrorMessage = null;
                return true;
            }
            else
            {
                validationErrorMessage = string.Format(CultureInfo.InvariantCulture, ParsingErrorMessage, DisplayName ?? FieldIdentifier.FieldName);
                return false;
            }
        }

        /// <summary>
        /// Formats the value as a string. Derived classes can override this to determine the formatting used for <c>CurrentValueAsString</c>.
        /// </summary>
        /// <param name="value">The value to format.</param>
        /// <returns>A string representation of the value.</returns>
        protected override string? FormatValueAsString(TValue? value)
        {
            // Avoiding a cast to IFormattable to avoid boxing.
            switch (value)
            {
                case null:
                    return null;

                case int @int:
                    return BindConverter.FormatValue(@int, CultureInfo.InvariantCulture);

                case long @long:
                    return BindConverter.FormatValue(@long, CultureInfo.InvariantCulture);

                case short @short:
                    return BindConverter.FormatValue(@short, CultureInfo.InvariantCulture);

                case float @float:
                    return BindConverter.FormatValue(@float, CultureInfo.InvariantCulture);

                case double @double:
                    return BindConverter.FormatValue(@double, CultureInfo.InvariantCulture);

                case decimal @decimal:
                    return BindConverter.FormatValue(@decimal, CultureInfo.InvariantCulture);

                default:
                    throw new InvalidOperationException($"Unsupported type {value.GetType()}");
            }
        }
    }

数值类型有好几种,但设置最大和最小一般为int类型,如果有特殊需求,代码就要复杂一点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落单枫叶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值