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

Blazor 如何在将EditForm绑定到数组时使EditContext.Validate()起作用,blazor,blazor-server-side,Blazor,Blazor Server Side,我创建了一个EditForm,将表格包装为: **Index.razor** @using System.ComponentModel.DataAnnotations; <EditForm @ref="Form" Model="vms" OnSubmit="Submit"> <DataAnnotationsValidator></DataAnnotationsValidator>

我创建了一个EditForm,将表格包装为:

**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] 答案也可以在这里找到。

简而言之,内置的DataAnnotationValidation不适用于数组。 要让它工作,你必须

installMicrosoft.AspNetCore.Components.DataAnnotations.Validation 将数组设为属性,然后用[ValidateComplexType]装饰它 使用ObjectGraphDataAnnotationsValidator
首先,我建议你这样做

<EditForm EditContext="editContext" OnSubmit="Submit">
顺便提一下,为什么使用OnSubmit而不是OnValidSubmit和OnInvalidSubmit?你在寻找挑战吗

验证返回不正确的结果

那不是真的

问题是您试图绑定到MyClass的数组……但是您应该绑定到单个对象。绑定到数组是可能的,但我不能扩展它,因为它需要一个新的问题。可以说,可以绑定到的对象数组本身必须是单个有界对象的字段属性,例如,包含他所说语言列表的Student对象

为了验证上述内容,请更改列表VM

进入MyClass模型=新建MyClass

和editContext=新的EditContextvms

into editContext=新的EditContextmodel

而不是

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

首先,我建议你这样做

<EditForm EditContext="editContext" OnSubmit="Submit">
顺便提一下,为什么使用OnSubmit而不是OnValidSubmit和OnInvalidSubmit?你在寻找挑战吗

验证返回不正确的结果

那不是真的

问题是您试图绑定到MyClass的数组……但是您应该绑定到单个对象。绑定到数组是可能的,但我不能扩展它,因为它需要一个新的问题。可以说,可以绑定到的对象数组本身必须是单个有界对象的字段属性,例如,包含他所说语言列表的Student对象

为了验证上述内容,请更改列表VM

进入MyClass模型=新建MyClass

和editContext=新的EditContextvms

into editContext=新的EditContextmodel

而不是

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

根据以下链接:,您应该在OnInitialized例程中创建一个新的EditContext,格式为EditContext=new EditContextvms。也许这会对您有所帮助我同意@JasonD,那么当您需要验证什么时,您可以使用:if editContext.validate{//SomeLogic}根据以下链接:,您应该在初始化例程中创建一个新的editContext,格式为editContext=new EditContextvms。也许这会对您有所帮助我同意@JasonD,那么当您需要验证什么时,您可以使用:if editContext.validate{//SomeLogic}谢谢您的回复。然而,我的奋斗目标是同时实现以下两件事:1。绑定到列表2。生成EditContext。验证工作。我尝试了您的建议,创建一个包装器类,然后将MyClass的列表作为属性包含到包装器中,但在我这样做之后,数据注释停止工作。也许我应该更好地回答我的问题,比如如何获取EditContext.Validate,以便在将EditForm绑定到数组时工作。请参阅我答案中的更新部分。如果它解决了您的问题,您是否介意将其标记为答案,以便其他人知道它是有用的。谢谢您的回复。然而,我的奋斗目标是同时实现以下两件事:1。绑定到列表2。生成EditContext。验证工作。我尝试了您的建议,创建一个包装器类,然后将MyClass的列表作为属性包含到包装器中,但在我这样做之后,数据注释停止工作。也许我应该更好地回答我的问题,比如如何获取EditContext.Validate,以便在将EditForm绑定到数组时工作。请参阅我答案中的更新部分。如果它解决了你的问题,你介意把它标记为答案吗?这样其他人就会知道它是有用的。
<tr>
     <td>
        <InputText @bind-Value="model.Code"></InputText>
        <ValidationMessage For="@(() => model.Code)"></ValidationMessage>
     </td>
 </tr>
@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; }
    }

}