Blazor中Virtualize结合EditForm与FluentValidation的全量验证问题
解决方案思路
核心问题拆解
Virtualize仅渲染可见行,导致绑定到EditContext的FluentValidation(EFV)只能验证已渲染的行;全量验证需要脱离EditContext的渲染依赖,直接验证数据集,同时要在滚动渲染行时同步错误状态。
具体实现步骤
1. 脱离EditContext,手动执行全量验证
直接使用FluentValidation的Validator实例对整个数据集进行验证,不依赖EditForm的渲染上下文:
- 创建Validator实例,遍历所有数据项逐个验证,将错误存入全局字典(用数据项唯一ID作为键):
// 全局存储所有数据项的验证错误 private Dictionary<int, List<ValidationFailure>> _validationErrors = new(); public async Task ValidateAllItems() { _validationErrors.Clear(); var validator = new YourItemValidator(); foreach (var item in YourDataset) { var result = await validator.ValidateAsync(item); if (!result.IsValid) { _validationErrors[item.Id] = result.Errors.ToList(); } } // 通知UI更新错误状态 StateHasChanged(); }
2. 滚动渲染时同步错误到行组件
在Virtualize渲染的行组件中,将全局错误字典中的错误同步到当前行的EditContext:
- 行组件接收数据项和错误字典作为参数,初始化或参数更新时手动同步错误:
@using FluentValidation.Results @using Microsoft.AspNetCore.Components.Forms <EditForm EditContext="_editContext"> <InputText @bind-Value="Item.Name" /> <ValidationMessage For="@(() => Item.Name)" /> <!-- 其他表单控件 --> </EditForm> @code { [Parameter] public YourItem Item { get; set; } [Parameter] public Dictionary<int, List<ValidationFailure>> ValidationErrors { get; set; } private EditContext _editContext; private ValidationMessageStore _messageStore; protected override void OnInitialized() { _editContext = new EditContext(Item); _messageStore = new ValidationMessageStore(_editContext); SyncValidationErrors(); } protected override void OnParametersSet() { SyncValidationErrors(); } private void SyncValidationErrors() { _messageStore.Clear(); if (ValidationErrors.TryGetValue(Item.Id, out var errors)) { foreach (var error in errors) { _messageStore.Add(_editContext.Field(error.PropertyName), error.ErrorMessage); } } _editContext.NotifyValidationStateChanged(); } }
3. 行内数据修改时实时更新错误
在行组件中,当数据项发生变化时,实时验证并更新全局错误字典:
[Parameter] public EventCallback<YourItem> OnItemUpdated { get; set; } private async Task OnItemChanged() { var validator = new YourItemValidator(); var result = await validator.ValidateAsync(Item); if (ValidationErrors.ContainsKey(Item.Id)) { ValidationErrors.Remove(Item.Id); } if (!result.IsValid) { ValidationErrors[Item.Id] = result.Errors.ToList(); } await OnItemUpdated.InvokeAsync(Item); }
替代方案
如果上述EFV手动验证方式不符合需求,可考虑:
- DataAnnotations手动验证:通过
Validator.TryValidateObject遍历数据集,将错误存入全局字典,后续同步逻辑与上述一致。 - 自定义验证服务:封装独立于UI的验证逻辑,直接对数据集进行验证并返回错误集合,由UI层根据错误集合渲染状态。
内容的提问来源于stack exchange,提问作者Jeremy Beare
相关产品推荐
相关产品推荐

