Blazor组件加载数据后未重新渲染问题求助
我创建了一个绑定供应商长列表的DropDownList组件ContractVendorSelect,代码拆分在ContractVendorSelect.razor和代码后置文件ContractVendorSelect.razor.cs中,并在Test.razor页面引用该组件。当前问题是:当IsLoaded标记设为true(表示供应商列表已获取完成)后,组件始终显示“Loading vendors ...”提示,没有重新渲染出下拉框。我已经尝试在多处调用StateHasChanged()方法,但问题依旧。
相关代码
ContractVendorSelect.razor
<div class="k-form-field-wrap"> @if (IsLoaded) { <select @bind=Contract.Vendor> <option>-- Select</option> @foreach (var item in VendorData) { <option value="@item.Value">@item.Text</option> } </select> } else { <span>Loading vendors ... </span> } </div>
ContractVendorSelect.razor.cs
public partial class ContractVendorSelect : FormFieldBase { [Parameter] public Contract? Contract { get; set; } [Parameter] public string? Id { get; set; } = null; [Parameter] public string? Label { get; set; } = null; [Parameter] public Sites? Site { get; set; } = null; protected bool IsLoaded { get; set; } = false; internal List<VendorSelectData>? VendorData { get; set; } = new List<StiVendorSelectData>(); private async Task SetVendorList() { if (Site != null) { var stagedData = await VendorSearch.GetVendorsAsync(this.Site.DBName); VendorData = new List<VendorSelectData>(); foreach(Vendor vendor in stagedData) { VendorData.Add(new VendorSelectData(vendor.Vendor_Name, vendor.Vendor_Key, vendor)); } IsLoaded = true; } } protected async override Task OnInitializedAsync() { await this.SetVendorList(); StateHasChanged(); } internal class VendorSelectData { public long Value { get; set; } public String Text { get; set; } public Vendor Vendor { get; set; } public VendorSelectData(string text, long value, Vendor model) { Text = text; Value = value; Vendor = model; } } }
Test.razor
<ContractVendorSelect Id="ddlContractVendor" Label="Vendor" Contract="contract" Site="site"> </ContractVendorSelect> @code { protected Contract contract { get; set; } protected Sites site { get; set; } public async Task SetContract() { contract = await ContractSearch.FindContract(<contractID>); } public async Task SetSite() { site = await SiteSearch.GetSiteByIDAsync(<SiteID>); } protected override async Task OnInitializedAsync() { await SetSite(); await SetContract(); } }
1. 修复参数传递的语法错误
在Test.razor中,组件参数绑定缺少@符号,导致传递的是字符串字面量而非变量,组件无法获取到有效的Site和Contract实例:
<ContractVendorSelect Id="ddlContractVendor" Label="Vendor" Contract="@contract" Site="@site"> </ContractVendorSelect>
2. 监听Site参数变化,延迟加载数据
父组件Test.razor的OnInitializedAsync是异步执行的,ContractVendorSelect的OnInitializedAsync可能在site赋值完成前就已执行,导致Site为null,SetVendorList逻辑未触发。重写OnParametersSetAsync方法监听参数变化:
protected override async Task OnParametersSetAsync() { if (Site != null && !IsLoaded) { await SetVendorList(); // 异步方法完成后Blazor会自动触发渲染,无需手动调用StateHasChanged } }
同时移除OnInitializedAsync中的SetVendorList调用,避免初始化时因Site为空导致逻辑失效。
3. 修正VendorData初始化的类型错误
代码中VendorData初始化时使用了错误的泛型类型StiVendorSelectData,与定义的List<VendorSelectData>不匹配,修正为:
internal List<VendorSelectData>? VendorData { get; set; } = new List<VendorSelectData>();
4. 验证异步操作执行状态
在SetVendorList中添加日志输出,确认数据是否成功加载、IsLoaded是否被正确设置:
private async Task SetVendorList() { if (Site != null) { Console.WriteLine("开始加载供应商数据"); var stagedData = await VendorSearch.GetVendorsAsync(this.Site.DBName); Console.WriteLine($"加载完成,共{stagedData.Count}条数据"); VendorData = new List<VendorSelectData>(); foreach(Vendor vendor in stagedData) { VendorData.Add(new VendorSelectData(vendor.Vendor_Name, vendor.Vendor_Key, vendor)); } IsLoaded = true; Console.WriteLine($"IsLoaded已设为{IsLoaded}"); } else { Console.WriteLine("Site参数为空,跳过数据加载"); } }
内容的提问来源于stack exchange,提问作者Gary O. Stenstrom

