上一篇寫數據綁定的文章,寫到最後留了一個坑。當子組件綁定父組件的一個欄位,並且子組件修改它的時候父組件不能實時進行同步更新UI的問題,最近終於在Blazui作者的指導下搞定了。 UserInfo類要實現INotifyPropertyChanged介面 public class UserInfo: I ...
上一篇寫數據綁定的文章,寫到最後留了一個坑。當子組件綁定父組件的一個欄位,並且子組件修改它的時候父組件不能實時進行同步更新UI的問題,最近終於在Blazui作者的指導下搞定了。
UserInfo類要實現INotifyPropertyChanged介面
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;
}
沒想到微軟blazor還是借用了WPF搞MVVM的模式,模型需要實現INotifyPropertyChanged類,在屬性發生修改的時候可以發出通知。
父組件訂閱PropertyChanged事件:
@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");
}
}
父組件訂閱子組件的PropertyChanged事件,當事件發生的時候調用組件的StateHasChanged方法。StateHasChanged方法會通知組件說狀態發生變化了,也就是說組件會被重新渲染。這就是最關鍵的東西了。
子組件
====================child==================
<p>
userName: <input @bind="UserInfo.UserName" @bind:event="oninput" />
</p>
<p>
sex:
<select @bind="UserInfo.Sex">
<option value="m">男</option>
<option value="f">女</option>
</select>
</p>
<p>
BrithDay:<input @bind="UserInfo.BrithDay" />
</p>
<button class="btn btn-danger" @onclick="InvokeChanged">保存</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");
}
}
運行
一些吐槽
雖然搞定了子父組件同步的問題,但是我不能理解的是,為什麼微軟要搞的這麼複雜。使用@bind-UserInfo會強制用戶在子組件實現一個 EventCallback