Blazor将EditForm拆分为多个子组件后数据同步异常如何解决
问题根因
你遇到的同步差异问题本质是子组件内触发的字段变更没有通知到主组件触发重绘:
- 修改主组件内的1a/1b时,EditForm的EditContext触发字段变更事件,主组件本身会自动重绘,连带刷新子组件参数,所以全量字段都会同步更新
- 修改子组件内的2a/2b/3a/3b时,EditContext的变更事件只会触发子组件重绘,主组件没有感知到变更不会重绘,所以只有子组件内的字段会更新
解决方案
方案1(推荐):让模型类实现INotifyPropertyChanged
这是最符合Blazor数据绑定规范的方案,属性变更时会主动通知所有绑定该属性的组件自动重绘,无需手动处理渲染逻辑:
using System.ComponentModel; using System.Runtime.CompilerServices; public class TestObject : INotifyPropertyChanged { private string _address; public string Address { get => _address; set { if (_address != value) { _address = value; OnPropertyChanged(); } } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
方案2:监听EditContext的字段变更事件手动触发重绘
如果不想修改模型类,可以直接在主组件监听EditForm自带的EditContext的FieldChanged事件,手动触发主组件重绘,修改Form.razor代码如下:
<h1>Field 1a and 1b</h1> <!-- 给EditForm加引用获取EditContext --> <EditForm Model="@TestObject" @ref="_editForm"> <MgInputText @bind-Value="TestObject.Address"/> <MgInputText @bind-Value="TestObject.Address" /> <Test /> </EditForm> @code { private EditForm _editForm; private TestObject TestObject = new(); protected override void OnAfterRender(bool firstRender) { if (firstRender) { // 监听全局字段变更事件,触发主组件重绘 _editForm.EditContext.FieldChanged += (sender, e) => StateHasChanged(); } } }
额外优化建议
你当前自定义的TestObject级联值可以去掉,直接用EditForm默认级联的EditContext获取模型即可,避免重复级联导致的上下文不一致问题,修改Test.razor代码:
<h1>Field 2a and 2b - GroupBox</h1> <GroupBox> <Title>TestData</Title> <ChildContent> <MgInputText @bind-Value="TestObject.Address" /> <MgInputText @bind-Value="TestObject.Address" /> </ChildContent> </GroupBox> <h2>Field 3a and 3b - Not in Component</h2> <MgInputText @bind-Value="TestObject.Address" /> <MgInputText @bind-Value="TestObject.Address" /> @code{ // 直接接收EditForm默认级联的EditContext,无需自定义级联 [CascadingParameter] public EditContext EditContext { get; set; } public TestObject TestObject => EditContext?.Model as TestObject; }
内容的提问来源于stack exchange,提问作者Taladan
相关产品推荐
相关产品推荐

