首页 > 解决方案 > 如何设置 ValidationMessage.对于 Blazor 中的动态属性?

问题描述

文档的这一部分描述了如何显示验证消息。

<ValidationMessage For="() => Parameters.PropertyA"></ValidationMessage>      

如何动态设置 ValidationMessage.For 属性?

由于For是 type Expression<Func<TValue>>,我想传递一个 Func ,但这不会编译:

[Parameter]
public Func<string> PropertyLocator { get; set; }

<ValidationMessage For="PropertyLocator"></ValidationMessage>

这会编译,但验证消息将无法正确解析

<ValidationMessage For="() => PropertyLocator"></ValidationMessage>

我还尝试使组件通用,以便它知道Parameters类型:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Components;

public partial class MyComponent<TParam>
{
    [Parameter]
    public TParam Parameters { get; set; }

    [Parameter]
    public Func<TReportParam, string> PropertyLocator { get; set; }
}


@using System.Linq.Expressions
@typeparam TParam
<ValidationMessage For="@((Expression<Func<string>>)(() => PropertyLocator(this.Parameters)))"></ValidationMessage>


<MyComponent TParam="MyParameters" Parameters="BindToSomeValue" PropertyLocator="(parameters) => parameters.PropertyA" />

但这会导致以下运行时异常:

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] 未处理的异常呈现组件:提供的表达式包含不受支持的 InvocationExpression1。FieldIdentifier 仅支持对象的简单成员访问器(字段、属性)。System.ArgumentException:提供的表达式包含不受支持的 InvocationExpression1。FieldIdentifier 仅支持对象的简单成员访问器(字段、属性)。在 Microsoft.AspNetCore.Components.Forms.FieldIdentifier.Create[String](Expression`1 访问器) 在 Microsoft.AspNetCore.Components.Forms.FieldIdentifier.ParseAccessor[String](Expression`1 accessor, Object& model, String& fieldName) .AspNetCore.Components.Forms.ValidationMessage`1[[System.String, System.Private.CoreLib, 版本=5.0.0.0,

标签: c#validationblazorblazor-webassembly

解决方案


我创建了一个小示例页面。

该模型DataAnnotations用作验证机制。


    public class DemoInputModel
    {
        [Required]
        public String PropertyOne { get; set; }

        [MinLength(2)]
        public String PropertyTwo { get; set; }

        [MaxLength(5)]
        public String PropertyThree { get; set; }
    }

在页面上,模型被初始化并设置为编辑上下文。我们有三个文本输入和一个选择框。选择框可用于切换验证消息。如果更改了选择框的值,则将新表达式分配给ValidationMessage.


@using System.ComponentModel.DataAnnotations;
@using System.Linq.Expressions;

@page "/test"


<h1>ValidationMessageTest</h1>

<EditForm Model="_model">
    <DataAnnotationsValidator />

    <ValidationMessage For="ValidationResolver"></ValidationMessage>

    <InputText @bind-Value="_model.PropertyOne" />
    <InputText @bind-Value="_model.PropertyTwo" />
    <InputText @bind-Value="_model.PropertyThree" />

    <InputSelect @bind-Value="SelectedValidationProperty">
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
    </InputSelect>

    @*<ValidationSummary />*@

</EditForm>


@code {

    private DemoInputModel _model = new DemoInputModel
    {
        PropertyOne = "Test",
        PropertyTwo = "42",
        PropertyThree = "Math.PI",
    };

    private String _selectedValidationProperty;

    public String SelectedValidationProperty
    {
        get => _selectedValidationProperty;
        set
        {
            _selectedValidationProperty = value;
            ChangeValidator(value);
        }
    }

    public Expression<Func<String>> ValidationResolver { get; set; }

    protected override void OnInitialized()
    {
        SelectedValidationProperty = "1";
        base.OnInitialized();
    }

    public void ChangeValidator(String value)
    {
        switch (value)
        {
            case "1":
                ValidationResolver = () => _model.PropertyOne;
                break;
            case "2":
                ValidationResolver = () => _model.PropertyTwo;
                break;
            case "3":
                ValidationResolver = () => _model.PropertyThree;
                break;
            default:
                break;
        }
    }
}

你的意思是这样的吗?如果你的模型不只有字符串,它会稍微复杂一些,就像例子中一样。一个“快速”的解决方法可能是Expression为每种可能的类型设置一个。

在引擎盖下,表达式用于创建一个FieldIdentifier. 然后 FieldIdentifier用于从 获取相应的属性/字段EditContext以检查验证状态。因此,您在为表达式选择什么方面受到限制。错误消息FieldIdentifier 仅支持对象的简单成员访问器(字段、属性)很好地表明了此限制。


推荐阅读