文档的本节描述了如何显示验证消息。
<ValidationMessage For="() => Parameters.PropertyA"></ValidationMessage> 如何动态设置ValidationMessage.For属性?
由于For是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.WebAssemblyRenderer100未处理异常呈现组件:提供的表达式包含不支持的InvocationExpression1。FieldIdentifier只支持对象的简单成员访问器(字段、属性)。System.ArgumentException:提供的表达式包含不支持的InvocationExpression1。FieldIdentifier只支持对象的简单成员访问器(字段、属性)。在Microsoft.AspNetCore.Components.Forms.FieldIdentifier.ParseAccessor字符串 at Microsoft.AspNetCore.Components.Forms.FieldIdentifier.Create字符串 at Microsoft.AspNetCore.Components.Forms.ValidationMessage`1[System.String,System.Private.CoreLib,Version=5.0.0.0,Culture=neutral,PublicKeyToken=7cec85d7bea7798e].OnParametersSet() at Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync() at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
发布于 2020-12-21 15:17:34
我创建了一个小样本页面。
该模型使用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只支持对象的简单成员访问器(字段、属性),这很好地说明了这一限制。
发布于 2020-12-21 15:12:40
我想通过一个Func代替
为什么?如果没有特定的原因需要传递Func<TValue>而不是Expression<Func<TValue>>,那么只需使用参数
[Parameter]
public Expression<Func<string>> PropertyLocator { get; set; }如果您只想要一个Func<>,因为您要将它重用为ValidationMessage的For参数以外的其他东西,那么您可以查看Extracting Func<> from Expression<>,以便从Expression<Func<string>> PropertyLocator获得Func<>。
如果您真的想传递一个Func<>,那么在尝试将.net函数转换为.net表达式时,可能会遇到一些问题需要转换。
发布于 2021-02-18 15:15:44
在进行了一些研究之后,我无意中发现了以下blazor特性:
装订的神圣三位一体
阅读更多关于它的这里。
简而言之,如果[Parameter]与折叠语法绑定.
<MyComponent @bind-Value="My.Binding.Path" />..。它不仅支持双向绑定,而且还设置一个定位器表达式。
[Parameter]
public string Value { get; set; }
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
[Parameter]
public Expression<Func<string>> ValueExpression { get; set; }您可以使用任何类型,而不是string。
由于ValueExpression的值是自动设置的,因此可以使用此行为显示绑定属性的验证消息。只需使用表达式将ValidationMessage组件添加到组件中即可。
<ValidationMessage For="ValueExpression" />一点额外的
如果您正在构建一个支持验证的组件(此时,我假设您是这样的)。以下可能也是您感兴趣的。
不仅可以使用神圣的三位一体来显示验证消息,还可以创建支持验证的组件。有许多关于这个主题的文章。
简言之:
EditContext上的字段更改要使上面创建的MyComponent的Value属性支持验证,只需遵循以下步骤。
定义一个CascadingParameter EditContext,这将获得当前的EditContext,通常来自EditForm组件。还请注意,如果没有EditContext,则可能不会设置CascadingValue。例如,如果组件未放置在EditForm中
[CascadingParameter]
public EditContext? EditContext定义一个属性来存储FieldIdentifier,并在设置参数时设置它。
public FieldIdentifier? FieldIdentifier { get; private set; }
public override async Task SetParametersAsync(ParameterView parameters)
{
await base.SetParametersAsync(parameters);
if (this.EditContext != null && this.DateExpression != null && this.FieldIdentifier?.Model != this.EditContext.Model)
{
this.FieldIdentifier = Microsoft.AspNetCore.Components.Forms.FieldIdentifier.Create(this.DateExpression);
}
}在需要时(通常在调用ValueChanged之后)触发字段的验证:
this.Value = value;
this.ValueChanged.InvokeAsync(this.Value);
if (this.FieldIdentifier?.FieldName != null)
{
this.EditContext?.NotifyFieldChanged(this.FieldIdentifier!.Value);
}https://stackoverflow.com/questions/65393962
复制相似问题