Blazor .NET 6服务端组件传参加载时触发TheDataChanged缺失错误
我在VS 2022中有一个Blazor .NET 6服务端项目,想实现Component1向Component2传递数据。
Component1代码
<!-- Component1.razor --> <input type="button" value="PassTheData" @onclick="PassTheData" />
// Component1.razor.cs [Parameter] public string TheData { get; set; } = string.Empty; [Parameter] public EventCallback<string> PassTheDataEvent { get; set; } private async void PassTheData() { TheData = "DATA!!!!!!!!!!!!!!!!!!"; await PassTheDataEvent.InvokeAsync(TheData); }
Component2代码
<!-- Component2.razor --> <h3>Comp 2</h3> The data is: @TheDataComp2
// Component2.razor.cs [Parameter] public string TheDataComp2 { get; set; } = string.Empty;
父组件实现思路及报错
我计划通过父页面中转数据:将Component1的属性绑定到父组件属性,再传递给Component2,父组件代码如下:
<!-- Parent1.razor --> <Comp1 @bind-TheData="theDataParent"></Comp1> <br /> <Comp2 TheDataComp2="@theDataParent"></Comp2>
// Parent1.razor.cs private string theDataParent = string.Empty;
但加载页面时出现错误:
[2023-08-24T17:45:15.942Z] Error: System.InvalidOperationException:
Object of type 'UI.Comp1' does not have a property matching the name
'TheDataChanged'. at
Microsoft.AspNetCore.Components.Reflection.ComponentProperties.ThrowForUnknownIncomingParameterName(Type
targetType, String parameterName) at
Microsoft.AspNetCore.Components.Reflection.ComponentProperties.SetProperties(ParameterView&
parameters, Object target) at
Microsoft.AspNetCore.Components.ParameterView.SetParameterProperties(Object
target) at
Microsoft.AspNetCore.Components.ComponentBase.SetParametersAsync(ParameterView
parameters) at
Microsoft.AspNetCore.Components.Rendering.ComponentState.SupplyCombinedParameters(ParameterView
directAndCascadingParameters)
我不理解为何会寻找名为TheDataChanged的属性,求助解决方法。移除@bind-TheData="theDataParent"标记后页面可正常加载。
错误原因
Blazor的@bind-*双向绑定语法有默认命名约定:当你使用@bind-TheData时,框架会自动查找对应的TheDataChanged事件回调(命名规则是参数名+Changed)。你的Component1里定义的事件是PassTheDataEvent,不符合这个约定,因此框架找不到对应的事件,抛出错误。
解决方法
方案一:修改子组件事件名称,符合双向绑定约定
把Component1的事件名称改为TheDataChanged,匹配Blazor的双向绑定规则:
// Component1.razor.cs 修改后 [Parameter] public string TheData { get; set; } = string.Empty; [Parameter] public EventCallback<string> TheDataChanged { get; set; } // 变更事件名称 // 建议将async void改为async Task,避免Blazor中潜在的异步问题 private async Task PassTheData() { TheData = "DATA!!!!!!!!!!!!!!!!!!"; await TheDataChanged.InvokeAsync(TheData); }
修改后,父组件的@bind-TheData="theDataParent"就能正常工作,点击Component1的按钮后,数据会自动同步到父组件的theDataParent,进而传递给Component2。
方案二:手动绑定参数和事件,不依赖默认约定
如果不想修改Component1的事件名称,可以在父组件中手动绑定参数和事件处理方法:
<!-- Parent1.razor 修改后 --> <Comp1 TheData="theDataParent" PassTheDataEvent="OnDataReceived"></Comp1> <br /> <Comp2 TheDataComp2="@theDataParent"></Comp2>
// Parent1.razor.cs 添加事件处理方法 private string theDataParent = string.Empty; private void OnDataReceived(string data) { theDataParent = data; }
点击Component1的按钮时,PassTheDataEvent会触发父组件的OnDataReceived方法,更新theDataParent的值,Component2会自动刷新显示新数据。
内容的提问来源于stack exchange,提问作者user8149311

