You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
        }
    }

    // 其他缺失的方法和变量请自行补充
}

问题根源及修复要点

  1. 验证上下文不匹配:原代码中validationContext未绑定当前编辑项,需在ValidateModel中基于传入的当前编辑实例创建验证上下文。
  2. 异步方法冗余:Validator.TryValidateObject是同步方法,无需用async/await包装,多余的Task.Delay只会延迟UI更新,毫无作用。
  3. 获取当前编辑项:通过Grid.GetCurrentEditRecord<unknownasgdata>()确保验证的是弹窗中正在编辑的对象,而非全局变量。
  4. 重渲染触发时机:验证失败后直接调用InvokeAsync(StateHasChanged)即可触发UI更新,无需额外的Task.Yield或延迟。

内容的提问来源于stack exchange,提问作者ComfortableOnion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 10:47:32