blazor - 通知 EditContext 该字段已更改以进行 Blazor 验证
问题描述
我试图了解 Blazor 的内部工作原理(并最终编写一些中间件)。我有一个小提琴,它以三种不同的方式绑定三个不同的字段:
- FirstName 字段绑定到 InputText 按预期工作,并在清除框和焦点更改时显示验证消息。
- MiddleName 字段绑定到常规输入并且不能“按预期”工作,并且在清除它并且焦点更改时不显示任何验证消息。通过 Blazor 源,我发现 EditContext.NotifyFieldChanged 如果控件本身(InputBase)是一个问题。
- 值得注意的是,如果您提交我想了解所涉及的生命周期的表单,则会显示该消息。
- LastName 字段也绑定到常规输入,但需要做一些小技巧来引发 EditContext.OnFieldChanged 并触发验证工作。 有没有更好的方法来为 onchange 做到这一点?提交如何设法引发验证消息? 有很多引用捕获、表达式、反射,以及“仅供内部使用”的 CreateBinder 方法的使用。
下面是小提琴的代码,以便于参考:
@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);
}
}
解决方案
您EditForm
包含一个提交按钮,因此当您单击该按钮时,会EditForm
识别提交操作并将其称为 internal HandleSubmitAsync
。即使您没有附加到 的处理程序,EditForm
此方法也会调用Validate
. EditContext
这将验证您的所有验证属性属性model
,在您的情况下是实际的组件(页面)。
OnChange
只要你对如何InputBase
、工作和交互EditForm
有很好的理解,你手动处理和设置是没有问题的。EditContext
您只是在复制InputBase
. 调用NotifyFieldChanged
会维护EditContext
. 但是,请注意,这并不是编辑状态的真正表示,它仅针对最后一次编辑而不是原始模型维护状态。
由于这是一个演示,因此使用组件作为模型是可以的,但是您应该为模型提供适当的数据类(您几乎可以肯定已经知道这一点,但其他人可能稍后会阅读此答案,...)。
推荐阅读
- android - 自 5 月 7 日以来,Google Play 控制台在所有应用中显示不正确的数据
- python - 有多个场景时如何拆分一列(熊猫)
- python - 无法删除类的实例
- r - 简化没有 for 循环的嵌套列表
- asp.net-core - Nlog - 数据库目标延迟
- android - 如果用户删除了应用程序或更换了手机,如何恢复用户帐户?
- firebase - Firebase Firestore 安全规则不起作用
- javascript - 如何使用 Javascript 获得正确的内部 HTML 文本?我继续获得未定义的值
- c# - 为什么内部 TransactionScope 的 IsolationLevel 不能不同,而 SQL 事务可以?
- python - 无法使用 socket.accept 终止进程