英文:
Blazor - how do I update a value in parent from child setting state
问题
我已经创建了一个状态容器:
public class StateContainer
{
public List<Jewellery> basket = new List<Jewellery>();
public void Add(Jewellery item)
{
basket.Add(item);
NotifyStateChanged();
}
public void Remove(Jewellery item)
{
var removeVal = basket.FindIndex(m => m.Id == item.Id);
basket.RemoveAt(removeVal);
NotifyStateChanged();
}
public event Action? OnChange;
private void NotifyStateChanged() => OnChange?.Invoke();
}
在一个对话框页面上,我有一个按钮用于添加和另一个按钮用于从我的 StateContainer 对象中移除值,这一切都运行良好。
在我的 Program.cs 文件中,我已经将该服务注册为 Singleton:
builder.Services.AddSingleton<StateContainer>();
目前,我有一个标题组件,其中包含:
<div>@StateContainer.basket.Count</div>
在将项目添加到篮子后,关闭对话框后,我希望能够立即在标题中看到计数。我应该如何在我的标题组件中绑定 StateContainer 以便它能够立即响应变化?
英文:
So I have created a state container:
public class StateContainer
{
public List<Jewellery> basket = new List<Jewellery>();
public void Add(Jewellery item)
{
basket.Add(item);
NotifyStateChanged();
}
public void Remove(Jewellery item)
{
var removeVal = basket.FindIndex(m=>m.Id == item.Id);
basket.RemoveAt(removeVal);
NotifyStateChanged();
}
public event Action? OnChange;
private void NotifyStateChanged() => OnChange?.Invoke();
}
On a Dialog page I have a button to add and another to remove the values From my StateContainer object and this works fine.
In my Program.cs file I have registered the service as Singleton:
builder.Services.AddSingleton<StateContainer>();
I have a header component for now with:
<div>@StateContainer.basket.Count</div>
After I adding an item into the basket, after I close the dialog I want to be able to see the count in my header. How should I bind the StateContainer in my header component so that it acts on the change immediately?
答案1
得分: 0
Your component containing the header should listen to the OnChange event. To do this, you can override the OnInitialized method and subscribe to the event. Then, when the event is triggered, just call StateHasChanged()
which will re-render the component.
protected override void OnInitialized()
{
stateContainer.OnChange += StateContainedChanged;
base.OnInitialized();
}
void StateContainedChanged()
{
InvokeAsync(StateHasChanged);
}
PS: I call InvokeAsync()
here because the event could be triggered by a non-main thread. So I make sure the StateHasChanged
method is called by the main thread.
When you subscribe to an event, in order to prevent memory leaks, it is important to unsubscribe. You can do it when your component is disposing:
@implements IDisposable
public void Dispose()
{
stateContainer.OnChange -= StateContainedChanged;
}
You could also use an ObservableCollection<Jewellery>
instead of a List<Jewellery>
. The ObservableCollection already implements an OnCollectionChanged
event and is able to tell what change is made.
英文:
Your component containing the header should listen the OnChange event.
To do this, you can override the OnInitialized method and suscribe to the event. Then when the event is triggered, just call StateHasChanged()
which will re-render the component.
protected override void OnInitialized()
{
stateContainer.OnChange += StateContainedChanged;
base.OnInitialized();
}
void StateContainedChanged()
{
InvokeAsync(StateHasChanged);
}
PS: I call InvokeAsync()
here because the event could be triggered by a non main thread. So I make sure the StateHasChanged
method is called by the main thread.
When you subcribe to an event, in order to prevent memory leaks, it is important to unsubscribe.
You can do it when your component is disposing :
@implements IDisposable
public void Dispose()
{
stateContainer.OnChange -= StateContainedChanged;
}
You could also use an ObservableCollection<Jewellery>
instead of a List<Jewellery>
.
The ObservableCollection already implements an OnCollectionChanged
event and is able to tell what change is made
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论