我有一个使用editcontext的editform:
<EditForm OnValidSubmit="HandleValidSubmit" EditContext="_editContext" Context="auth">
<DataAnnotationsValidator />
<input type="time" @bind-value="_foodTruck.EndDelivery" @onkeydown="@(q=>ResetValidation("EndDelivery"))" >
<ValidationMessage For="() => _foodTruck.EndDelivery" />
<input type="time" @bind-value="_foodTruck.StartDelivery" @onkeydown="@(q=>ResetValidation("StartDelivery"))" >
<ValidationMessage For="() => _foodTruck.StartDelivery" />
<input class="btn btn-default" type="submit" value="save" />
</EditForm>
我在HandleValidSubmit中进行了一些自定义验证:
EditContext _editContext = new EditContext(_foodTruck);
private async void HandleValidSubmit()
{
var messageStore = new ValidationMessageStore(_editContext);
if (_foodTruck.StartDelivery >= _foodTruck.EndDelivery)
{
messageStore.Add(_editContext.Field("EndDelivery"), "Bad time entered");
_editContext.NotifyValidationStateChanged();
}
if (!_editContext.Validate()) return;
}
现在发生的是,我的自定义错误(“输入错误时间”)显示在正确的位置。唯一的问题是:更改值后该错误不会消失。因此,如果我单击“提交”按钮,就永远不会再次调用HandleValidSubmit。
我还尝试在修改字段时清空验证错误:
protected void ResetValidation(string field)
{
var messageStore = new ValidationMessageStore(_editContext);
messageStore.Clear(_editContext.Field(field));
messageStore.Clear();
_editContext.NotifyValidationStateChanged();
}
这由onkeydown
调用。但这似乎也不起作用。错误消息不会消失,因此HandleValidSubmit
也不会被调用。
答案 0 :(得分:4)
我通过在Validation-reset上创建一个新的EditContext解决了这一问题。所以我只是将以下行添加到ResetValidation-Method中:
_editContext = new EditContext(_foodTruck);
但是说实话:那感觉不对。因此,我将保持开放状态,以便更好地回答(希望如此)。
答案 1 :(得分:1)
我有同样的问题。我找不到简单的解决方案。类似于下面的解决方法对我有用。
按如下所示修改EditForm-
<EditForm EditContext="_editContext" OnSubmit="HandleSubmit">
@代码块
EditContext _editContext;
ValidationMessageStore msgStore;
FoodTruck _foodTruck= new FoodTruck();
protected override void OnInitialized()
{
_editContext = new EditContext(_foodTruck);
msgStore = new ValidationMessageStore(_editContext);
}
void HandleSubmit()
{
msgStore.Clear();
if(_editContext.Validate()) // <-- Model Validation
{
if (_foodTruck.StartDelivery >= _foodTruck.EndDelivery) //<--Custom validation
{
msgStore = new ValidationMessageStore(_editContext);
msgStore.Add(_editContext.Field("EndDelivery"), "Bad time entered");
}
}
}
答案 2 :(得分:0)
在事件操作的末尾添加this.StateHasChanged(),以便它可以再次呈现ui元素并删除验证消息。
EditContext _editContext = new EditContext(_foodTruck);
private async void HandleValidSubmit()
{
var messageStore = new ValidationMessageStore(_editContext);
if (_foodTruck.StartDelivery >= _foodTruck.EndDelivery)
{
messageStore.Add(_editContext.Field("EndDelivery"), "Bad time entered");
_editContext.NotifyValidationStateChanged();
this.StateHasChanged(); //this line
}
if (!_editContext.Validate()) return;
}
对于另一个
protected void ResetValidation(string field)
{
var messageStore = new ValidationMessageStore(_editContext);
messageStore.Clear(_editContext.Field(field));
messageStore.Clear();
_editContext.NotifyValidationStateChanged();
this.StateHasChanged(); //this line
}
请让我知道它是否有效
答案 3 :(得分:0)
我遇到了与原始海报相同的问题,因此我决定在EditContext的源代码中四处浏览(谢谢source.dot.net!)。因此,我提出了一个解决方法,该解决方法足以满足Blazor团队在将来的版本中正确解决该问题的要求。
/// <summary>
/// Contains extension methods for working with the <see cref="EditForm"/> class.
/// </summary>
public static class EditFormExtensions
{
/// <summary>
/// Clears all validation messages from the <see cref="EditContext"/> of the given <see cref="EditForm"/>.
/// </summary>
/// <param name="editForm">The <see cref="EditForm"/> to use.</param>
/// <param name="revalidate">
/// Specifies whether the <see cref="EditContext"/> of the given <see cref="EditForm"/> should revalidate after all validation messages have been cleared.
/// </param>
/// <param name="markAsUnmodified">
/// Specifies whether the <see cref="EditContext"/> of the given <see cref="EditForm"/> should be marked as unmodified.
/// This will affect the assignment of css classes to a form's input controls in Blazor.
/// </param>
/// <remarks>
/// This extension method should be on EditContext, but EditForm is being used until the fix for issue
/// <see href="https://github.com/dotnet/aspnetcore/issues/12238"/> is officially released.
/// </remarks>
public static void ClearValidationMessages(this EditForm editForm, bool revalidate = false, bool markAsUnmodified = false)
{
var bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
object GetInstanceField(Type type, object instance, string fieldName)
{
var fieldInfo = type.GetField(fieldName, bindingFlags);
return fieldInfo.GetValue(instance);
}
var editContext = editForm.EditContext == null
? GetInstanceField(typeof(EditForm), editForm, "_fixedEditContext") as EditContext
: editForm.EditContext;
var fieldStates = GetInstanceField(typeof(EditContext), editContext, "_fieldStates");
var clearMethodInfo = typeof(HashSet<ValidationMessageStore>).GetMethod("Clear", bindingFlags);
foreach (DictionaryEntry kv in (IDictionary)fieldStates)
{
var messageStores = GetInstanceField(kv.Value.GetType(), kv.Value, "_validationMessageStores");
clearMethodInfo.Invoke(messageStores, null);
}
if (markAsUnmodified)
editContext.MarkAsUnmodified();
if (revalidate)
editContext.Validate();
}
}
答案 4 :(得分:0)
遇到了同样的问题,使用EditContext.Validate()
以一种不太hacky的方式解决了该问题:
我已经实现了一种名为EditContext_OnFieldChanged(object sender, FieldChangedEventArgs e)
的方法,该方法会在使用EditForm使用的模型的参数后立即被调用。它是这样实现的:
protected override void OnInitialized()
{
EditContext = new EditContext(ModelExample);
EditContext.OnFieldChanged += EditContext_OnFieldChanged;
}
这里是方法:
private void EditContext_OnFieldChanged(object sender, FieldChangedEventArgs e)
{
EditContext.Validate();
// ...
// other stuff you want to be done when the model changes
}
EditContext.Validate()
似乎会更新所有验证消息,甚至是自定义消息。