如何在继承的组件中自动设置事件回调?

How to set event callback automatically in inherited component?

目前我有:

<InputText @oninput="@SomeHandler" />

现在我需要使用仅 class 的组件从 InputText 继承,我想在这个新组件中自动设置事件处理程序,所以我会像这样使用新组件:

<CustomInputText />

如何在自定义组件中设置事件处理程序?

<InputText @oninput="@SomeHandler" />

@oninput 是一个编译器属性指令,旨在与 Html 标记一起使用,而不是与组件一起使用。 InputText 是组件标签,而不是 Html 标签。过去,此类应用程序会被忽略或引发编译错误;然而,目前,编译器属性指令可能会由编译器静默添加,但通常会导致难以辨别的细微问题。你应该尽量避免这种情况。

如果你想子class InputText 并像这样使用它:<CustomInputText />,

您只需从 InputText 派生,如下所示:

public partial class CustomInputText : InputText
{
   // Add here the internal work...
}

并在EditForm上使用(注意:必须嵌入在EditForm组件中),像这样:

<EditForm>
   <CustomInputText />
</EditForm>

I would like to set òninput=SomeHandler (or an equivalent) directly in the ctor or OnAfterRender of the custom component

重要的是要了解虽然组件是 C# class,但它是 class 的特例,您不应尝试将其用作普通 C# class。例如,你不应该像这样实例化一个组件:

CustomInputText MyCustomInputText = new CustomInputText();

然后调用它的方法和属性,就好像它是一个普通的 C# class 对象一样。您应该像这样将其实例化为组件元素:

<CustomInputText @bind-Value="myValue" /> 

这是因为组件模型的渲染引擎正确地进行了实例化...现在,如果您将组件实例化为一个普通的 C# class 对象,您将跳过对渲染引擎,在最好的情况下会使您的组件无用。我告诉你这是因为你应该忘记构造函数的概念。没有构造函数...

Blazor 具有生命周期方法,您应该在初始化组件时重写这些方法。

下面是描述如何子class InputText 组件的代码示例...复制测试和学习:

NumericInputText.razor.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Web;


 public partial class NumericInputText : InputText
    {
        protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.OpenElement(0, "input");
            __builder.AddAttribute(1, "type", "number");
            __builder.AddMultipleAttributes(2, AdditionalAttributes);
            __builder.AddAttribute(3, "class", CssClass);
            __builder.AddAttribute(4, "value", CurrentValueAsString);
            __builder.AddEventPreventDefaultAttribute(5, "onkeypress", true);
            __builder.AddAttribute(6, "onblur", Microsoft.AspNetCore.Components.EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.FocusEventArgs>(this, OnBlurEventHandler));
            __builder.AddAttribute(7, "onkeydown", Microsoft.AspNetCore.Components.EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.KeyboardEventArgs>(this, OnKeyDown));
            __builder.AddAttribute(8, "oninput", Microsoft.AspNetCore.Components.EventCallback.Factory.Create<Microsoft.AspNetCore.Components.ChangeEventArgs>(this, OnInput));
            __builder.CloseElement();
        }

        protected override void OnInitialized()
        {
            CurrentValueAsString = "0";
        }

        private void OnInput(ChangeEventArgs args)
        {
         
            if (args.Value.ToString() == "")
            {
                CurrentValueAsString = "0";
            }
            else
            {
                CurrentValueAsString = args.Value.ToString();

            }
        }

        private void OnKeyDown(KeyboardEventArgs e)
        {
            if (e.Key == "Backspace" && CurrentValueAsString.Length == 1)
            {
                CurrentValueAsString = "";
            }


            if (e.Key == "+")
            {
                var value = int.Parse(CurrentValueAsString);
                value++;
                CurrentValueAsString = value.ToString();
            }
            else if (e.Key == "-")
            {
                var value = int.Parse(CurrentValueAsString);
                value--;
                CurrentValueAsString = value.ToString();
            }


            if (Regex.IsMatch(e.Key, "[0-9]"))
            {
                CurrentValueAsString += int.Parse($"{e.Key}").ToString();

            }

        }

        protected void OnBlurEventHandler(Microsoft.AspNetCore.Components.Web.FocusEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(CurrentValueAsString))
            {
                CurrentValueAsString = "0";
            }

        }

    }  

用法

<EditForm Model="@Model" OnValidSubmit="@HandleValidSubmit" OnInvalidSubmit="@HandleInvalidSubmit">
    <div class="alert @StatusClass">@StatusMessage</div>
    <DataAnnotationsValidator />
    <ValidationSummary />

    <div class="form-group">
        <label for="name">Name: </label>
        <NumericInputText Id="name" Class="form-control" @bind-Value="@Model.NumberSelection" />
        <ValidationMessage For="@(() => Model.NumberSelection)" />
    </div>


    <button type="submit">Ok</button>

</EditForm>

@code {

    private string StatusMessage;
    private string StatusClass;

    private Comment Model = new Comment();

    protected void HandleValidSubmit()
    {
        StatusClass = "alert-info";
        StatusMessage = DateTime.Now + " Handle valid submit";
    }

    protected void HandleInvalidSubmit()
    {
        StatusClass = "alert-danger";
        StatusMessage = DateTime.Now + " Handle invalid submit";
    }


    public class Comment
    {
        public string NumberSelection { get; set; }

    }

}