Last Write Data Binding The article left a hole at the end.When a child component binds a field of the parent component and the child component modifies it, the parent component cannot synchronously update the UI in real time. Recently, the problem was finally solved in Blazui Under the guidance of the author.
UserInfo class implements the INotifyPropertyChanged interface
public class UserInfo: INotifyPropertyChanged { private string _userName; public string UserName { get { return _userName; } set { _userName = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(UserName))); } } public string Sex { get; set; } public DateTime BrithDay { get; set; } public event PropertyChangedEventHandler PropertyChanged; }
Unexpectedly, Microsoft blazor borrowed the WPF model for MVVM. The model needs to implement the INotifyPropertyChanged class, which can be notified when properties are modified.
Parent component subscribes to PropertyChanged events:
@page "/" ====================parent```================== <p> userName: @userInfo.UserName </p> <p> sex: @userInfo.Sex </p> <p> brithday: @userInfo.BrithDay </p> <p> title: @title </p> <InfoEdit UserInfo="userInfo" UserInfoChanged="HandleUserInfoChanged"></InfoEdit> @code { private UserInfo userInfo; private string title; protected override void OnInitialized() { userInfo = new UserInfo { UserName = "abc", Sex = "f", BrithDay = DateTime.Now }; this.userInfo.PropertyChanged += (o, e) => StateHasChanged(); base.OnInitialized(); } private void HandleUserInfoChanged(UserInfo info) { this.userInfo = info; Console.WriteLine("HandleUserInfoChanged"); } }
The parent component subscribes to the child component's PropertyChanged event and invokes the component's StateHasChanged method when the event occurs.The StateHasChanged method notifies the component that the state has changed, which means the component will be re-rendered.That's what matters most.
Subcomponents
====================child================== <p> userName: <input @bind="UserInfo.UserName" @bind:event="oninput" /> </p> <p> sex: <select @bind="UserInfo.Sex"> <option value="m">male</option> <option value="f">female</option> </select> </p> <p> BrithDay: <input @bind="UserInfo.BrithDay" /> </p> <button @onclick="InvokeChanged">Preservation</button> @code { [Parameter] public UserInfo UserInfo { get; set; } [Parameter] public EventCallback<UserInfo> UserInfoChanged { get; set; } private void InvokeChanged() { UserInfoChanged.InvokeAsync(this.UserInfo); Console.WriteLine("InvokeChanged"); } }
Function
Some spitting slots
Although I've worked out the problem of child-parent component synchronization, what I can't understand is why Microsoft is so complex.Using @bind-UserInfo forces the user to implement an EventCallback UserInfoChanged event in the subcomponent.So since @bind:event="oninput" can write back the value of a segment in real time, so why not call UserInfoChanged directly and simultaneously to throw an event?Also, the parent component can refresh the UI while the compiler directly implants the listener for UserInfoChanged events.Maybe Microsoft wanted users to control the rendering timing of parent components manually for performance.