Blazor中调用StateHasChanged无法更新UI的问题求助
Blazor Syncfusion Grid 弹窗编辑无法显示数据注解验证错误
试遍所有方案都没用,各种解释看似合理但实际无效,现在完全没头绪。我手动检查数据模型有效性,模型无效时更新错误信息列表,但UI始终不展示这些错误。
组件代码
@using Syncfusion.Blazor.Grids @using Syncfusion.Blazor.Buttons @using Syncfusion.Blazor.Popups @using Syncfusion.Blazor.DropDowns @using Syncfusion.Blazor.Calendars @using Syncfusion.Blazor.Inputs @using Syncfusion.Blazor.SplitButtons @using Syncfusion.Blazor.Data @using Blazored.Toast.Services @using Microsoft.Data.SqlClient @using System.Text @using Syncfusion.Blazor.Spinner @using System.ComponentModel.DataAnnotations; <SfGrid ID="Grid" Query="@query" HtmlAttributes="htmlAttributes" DataSource="@transactions" @ref="Grid" AllowPaging="true" AllowFiltering="true" AllowExcelExport="true" AllowSorting="true" Toolbar="@(new List<string>() {"Edit", "ExcelExport" })"> <GridFilterSettings Type="Syncfusion.Blazor.Grids.FilterType.FilterBar"></GridFilterSettings> <GridPageSettings PageCount="5" PageSize="20" PageSizes="@(new string[] { "5", "10", "20", "40", "50", "All" })"></GridPageSettings> <GridSelectionSettings Type="Syncfusion.Blazor.Grids.SelectionType.Multiple"></GridSelectionSettings> <GridEvents OnActionBegin="ActionBeginHandler" OnToolbarClick="ToolbarClick" TValue="unknownasgdata"></GridEvents> <GridEditSettings AllowAdding="true" AllowEditing="true" AllowDeleting="true" Mode="EditMode.Dialog" Dialog="DialogParams" ShowConfirmDialog="true"> <Validator> <DataAnnotationsValidator></DataAnnotationsValidator> </Validator> <Template> @{ var unknownItem = (context as unknownasgdata); <div> @if (validationResults.Any()) { <div class="validation-summary text-danger"> @foreach (var validationResult in validationResults) { <div>@validationResult.ErrorMessage</div> } </div> } <br/> <div class="form-row"> <div class="form-group col-md-6"> <label><b>Bezeichnung</b></label><br /> @(unknownItem.description) </div> </div> <div class="form-row"> <div class="form-group col-md-6"> <label><b>Betriebsstätte</b></label><br /> @(unknownItem.house) </div> </div> <div class="form-row"> <div class="form-group col-md-6"> <label><b>Leistungsnummer</b></label><br /> @(unknownItem.leinr) </div> </div> <div class="form-row"> <div class="form-group col-md-6"> <label><b>Preis</b></label><br /> <SfNumericTextBox @bind-Value="@(unknownItem.articleprice)" ></SfNumericTextBox> </div> </div> <br/> <div class="form-row"> <div class="form-group col-md-6"> <label><b>Mahlzeitart</b></label><br/> <SfDropDownList TValue="string" TItem="string" DataSource="@(new List<string> { "Frühstück", "Mittagessen", "Abendessen" })" @bind-Value="@(unknownItem.selectedMahlzeit)"></SfDropDownList> </div> </div> </div> } </Template> <FooterTemplate> <SfButton OnClick="@SubmitForm" IsPrimary="true">Speichern</SfButton> <SfButton OnClick="Cancel">Abbrechen</SfButton> </FooterTemplate> </GridEditSettings> <GridColumns> <GridColumn Field=@nameof(unknownasgdata.description) HeaderText="Beschreibung"></GridColumn> <GridColumn Field=@nameof(unknownasgdata.leinr) HeaderText="Lst.Nummer" Width="150"></GridColumn> <GridColumn Field=@nameof(unknownasgdata.house) HeaderText="Betriebsstätte" Width="100"></GridColumn> </GridColumns> </SfGrid> @code{ private SfGrid<unknownasgdata> Grid { get; set; } private List<ValidationResult> validationResults = new List<ValidationResult>(); private bool ValidateModel(unknownasgdata model) { validationResults.Clear(); var validationContext = new ValidationContext(model); return Validator.TryValidateObject(model, validationContext, validationResults, true); } private async Task SubmitForm() { var currentItem = Grid.GetCurrentEditRecord<unknownasgdata>(); if (currentItem == null) return; if (ValidateModel(currentItem)) { // 执行数据库更新逻辑 // ... await Grid.EndEdit(); await Grid.Refresh(); } else { await InvokeAsync(StateHasChanged); } } // 其他缺失的方法和变量请自行补充 }
问题根源及修复要点
- 验证上下文不匹配:原代码中
validationContext未绑定当前编辑项,需在ValidateModel中基于传入的当前编辑实例创建验证上下文。 - 异步方法冗余:
Validator.TryValidateObject是同步方法,无需用async/await包装,多余的Task.Delay只会延迟UI更新,毫无作用。 - 获取当前编辑项:通过
Grid.GetCurrentEditRecord<unknownasgdata>()确保验证的是弹窗中正在编辑的对象,而非全局变量。 - 重渲染触发时机:验证失败后直接调用
InvokeAsync(StateHasChanged)即可触发UI更新,无需额外的Task.Yield或延迟。
内容的提问来源于stack exchange,提问作者ComfortableOnion
相关产品推荐
相关产品推荐

