首页 > 解决方案 > 通知 EditContext 该字段已更改以进行 Blazor 验证

问题描述

我试图了解 Blazor 的内部工作原理(并最终编写一些中间件)。我有一个小提琴,它以三种不同的方式绑定三个不同的字段:

小提琴

下面是小提琴的代码,以便于参考:

@page "/"
@using System.ComponentModel.DataAnnotations
@using System.Linq.Expressions;
@using System.Reflection;
@implements IHasEditContext;

<h1>Hello, world!</h1>

<EditForm EditContext="this.EditContextRef">
    <DataAnnotationsValidator></DataAnnotationsValidator>
    <div class="form-group">
        <InputText @bind-Value="@this.FirstName" class="form-control" />
        <ValidationMessage For="() => this.FirstName"></ValidationMessage>
    </div>
    <div class="form-group">
        <input @bind-value="@this.MiddleName" class="form-control" />
        <ValidationMessage For="() => this.MiddleName"></ValidationMessage>
    </div>
    <div class="form-group">
        <input value="@this.LastName" class="form-control" @onchange="(CreateBinder2(this, () => this.LastName,  this.LastName))" />
        <ValidationMessage For="() => this.LastName"></ValidationMessage>
    </div>


    <input type="submit" value="Go" />
</EditForm>

@code {
    protected override void OnInitialized()
    {
        base.OnInitialized();
        EditContextRef = new EditContext(this);
    }

    //BasicFormValidator Form1Validator = new BasicFormValidator();
    [Required]
    public String FirstName { get; set; } = "delete me and change focus to cause validation";
    [Required]
    public String MiddleName { get; set; } = "delete me and change focus - no validation";
    [Required]
    public String LastName { get; set; } = "delete me and change focus - validation but manually calling NotifyFieldChanged";

    public EditContext EditContextRef { get; set; }

    public static EventCallback<ChangeEventArgs> CreateBinder2(
        IHasEditContext receiver,
        Expression<Func<string?>> propExpression,
        string existingValue,
        System.Globalization.CultureInfo? culture = null)
    {
        var fieldIdentifier = FieldIdentifier.Create(propExpression);
        Action<String> valueSetter = (string v) =>
        {
            PropertyInfo prop = fieldIdentifier.Model.GetType().GetProperty(fieldIdentifier.FieldName, BindingFlags.Public | BindingFlags.Instance);
            prop.SetValue(fieldIdentifier.Model, v);
            receiver.EditContextRef.NotifyFieldChanged(fieldIdentifier);
        };

        return EventCallback.Factory.CreateBinder<string>(receiver, valueSetter, existingValue, culture);
    }


}

标签: blazorblazor-server-sideblazor-webassembly

解决方案


EditForm包含一个提交按钮,因此当您单击该按钮时,会EditForm识别提交操作并将其称为 internal HandleSubmitAsync。即使您没有附加到 的处理程序,EditForm此方法也会调用Validate. EditContext这将验证您的所有验证属性属性model,在您的情况下是实际的组件(页面)。

OnChange只要你对如何InputBase、工作和交互EditForm有很好的理解,你手动处理和设置是没有问题的。EditContext您只是在复制InputBase. 调用NotifyFieldChanged会维护EditContext. 但是,请注意,这并不是编辑状态的真正表示,它仅针对最后一次编辑而不是原始模型维护状态。

由于这是一个演示,因此使用组件作为模型是可以的,但是您应该为模型提供适当的数据类(您几乎可以肯定已经知道这一点,但其他人可能稍后会阅读此答案,...)。


推荐阅读