将 EditForm 绑定到数组时如何使 EditContext.Validate() 起作用

How to get EditContext.Validate() to work when binding EditForm to an array

我创建了一个 EditForm 包装一个 table 像这样:

**Index.razor**


@using System.ComponentModel.DataAnnotations;

<EditForm @ref="Form" Model="vms" OnSubmit="Submit">
    <DataAnnotationsValidator></DataAnnotationsValidator>
    <table class="table">
        <thead>
            <tr>
                <th>Code</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var vm in vms)
            {
                <tr>
                    <td>
                        <InputText @bind-Value="vm.Code"></InputText>
                        <ValidationMessage For="@(() => vm.Code)"></ValidationMessage>
                    </td>
                </tr>
            }
        </tbody>
    </table>
    <input type="submit" class="btn btn-primary" value="Submit" />
</EditForm>

@code{
    List<MyClass> vms;
    EditForm Form;
    class MyClass
    {
        [Required(ErrorMessage ="Required")]
        public string Code { get; set; }
    }
    protected override void OnInitialized()
    {
        vms = new List<MyClass>()
    {
            new MyClass()
            {
                Code = "1111"
            },
            new MyClass()
            {
                Code = "2222"
            }
        };
    }
    private void Submit()
    {
        bool IsValid = Form.EditContext.Validate();
    }
}

按照下图正确弹出消息错误:

但是,当我提交表单然后验证时,它似乎并没有选择无效状态。

调用EditContext.Validate()后仍然返回true,虽然有错误

如何让它工作? (当 EditForm 上下文中的至少一个模型项无效时,我如何得到 false,以便我可以进行其他验证?)


[2021-01-16 更新] 也可以在这里找到答案。 https://www.pragimtech.com/blog/blazor/validating-complex-models-in-blazor/

简而言之,内置的 DataAnnotationValidation 不适用于数组。 要使其正常工作,您必须

  1. installMicrosoft.AspNetCore.Components.DataAnnotations.Validation
  2. 将数组设为属性,然后用[ValidateComplexType]修饰它
  3. 使用 ObjectGraphDataAnnotationsValidator

首先,我建议你这样做

<EditForm EditContext="editContext" OnSubmit="Submit">

而不是

<EditForm @ref="Form" Model="vms" OnSubmit="Submit">

这需要您像这样定义 EditContext:EditContext editContext;

并在 OnInitialized 方法中实例化 EditContext 对象,如下所示:

protected override void OnInitialized()
    {
        vms = new List<MyClass>() { new MyClass() { Code = "1111" },
                                    new MyClass() { Code = "2222" }
                                  };

        editContext = new EditContext(vms);
    }

顺便说一下,为什么使用 OnSubmit 而不是 OnValidSubmitOnInvalidSubmit ?您在寻找挑战吗?

EditContext.Validate() returns incorrect results

这不是真的...

问题是您尝试绑定到 MyClass 的数组...但是您应该绑定到单个对象。绑定到一个数组是可能的,但我不能扩展它,因为它值得一个新问题。只要说您可以绑定的对象数组本身必须是单个有界对象的字段 (属性) 就够了,例如,包含他说的语言列表的 Student 对象。

为了验证以上内容,更改List<MyClass> vms;

进入MyClass model = new MyClass();

editContext = new EditContext(vms);

进入editContext = new EditContext(model);

而不是

 @foreach (var vm in vms)
  {
            <tr>
                <td>
                    <InputText @bind-Value="vm.Code"></InputText>
                    <ValidationMessage For="@(() => vm.Code)"> 
       </ValidationMessage>
                </td>
            </tr>
  }

代码如下:

<tr>
     <td>
        <InputText @bind-Value="model.Code"></InputText>
        <ValidationMessage For="@(() => model.Code)"></ValidationMessage>
     </td>
 </tr>

现在,运行你的代码,验证EditContext.Validate()的诽谤是否正当。

更新

以下代码示例描述了如何绑定到 EditForm 中的集合,以及如何验证该集合以及模型中的其他字段(该集合是该模型的字段成员)。

注意:您应该在包管理器控制台中执行 Install-Package Microsoft.AspNetCore.Components.DataAnnotations.Validation -Version 3.2.0-rc1.20223.4,以访问使示例工作所需的对象...

@page "/"
@using Microsoft.AspNetCore.Components.Forms
@using System.ComponentModel.DataAnnotations;

<EditForm EditContext="EditContext" OnSubmit="@OnSubmitHandler">
    @*<DataAnnotationsValidator />*@
    <ObjectGraphDataAnnotationsValidator/>
    <p>
        <label for="name">Enter name: </label>
        <InputText id="name" @bind-Value="customer.Name" /><br />
        <ValidationMessage For="@(() => customer.Name)" />
    </p>
    @foreach (var phone in customer.phones)
    {
<p>
    <label>Enter phone: </label>
    <InputText @bind-Value="phone.PhoneNumber" />
    <ValidationMessage For="@(() => phone.PhoneNumber)" />
</p>
    }

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

</EditForm>

<div>
    <p>Edit  customer</p>

    <p>@customer.Name</p>
    @foreach (var phone in customer.phones)
    {
        <p>@phone.PhoneNumber</p>

    }

</div>
<div>
     <p>Is model validated: @validated.ToString()</p>
 </div>
@code {
    EditContext EditContext;
    Customer customer;
    bool validated;

    protected override void OnInitialized()
    {
        customer = new Customer();
        EditContext = new EditContext(customer);

    }
    private void OnSubmitHandler()
    {            
        validated = EditContext.Validate();
    }

    public class Customer
    {
        [Required]
        public string Name { get; set; }  
        [ValidateComplexType]
        public List<Phone> phones { get; set; } = new List<Phone>() { new Phone { }, new Phone { }, new Phone { }};
         
    }

    public class Phone
    {
        [Required]
        public string PhoneNumber { get; set; }
    }

}