Blazor 自定义可重用基础组件之 NumberBox(InputNumber)

19 篇文章 1 订阅

只能输入数字的输入框,为避免命名冲突,先命名为NumberBox。

NumberBox.razor

@inherits InputBase<TValue>
@typeparam TValue
<div class="d-flex">
    <label class="control-label w-auto mt-2"><b>@Lable</b></label>
    <div style="width:@InputWidth">
        <input type="number" @bind-value="CurrentValueAsString" class="form-control" disabled="@Disabled" @ref="Element"  @attributes="AdditionalAttributes"/>
        <span class="w-100"><ValidationMessage For="ValueExpression" /></span>
    </div>
</div>

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; }

        protected override void OnParametersSet()
        {
            base.OnParametersSet();
            Lable += ":";
            InputWidth += "px;";
        }

        //以下是复制于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; }

        //这里是生成渲染树,我们用MyInputNumber.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))
            {
                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()}");
            }
        }
    }

使用:

<EditForm Model="MyNumber1">
    <p>
        <MyInputNumber Lable="数字测试" @bind-Value="MyNumber1.MyNumber1" InputWidth="300" ParsingErrorMessage="这里只能输入数字!" />
    </p>
</EditForm>
@code{
    private MyNumber MyNumber1 = new();
    internal class MyNumber
    {
        internal int MyNumber1 { get; set; }
    }
}

//其中加不加 TValue="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、付费专栏及课程。

余额充值