C# Blazor列表<;T>;更改T元素时缺少重新渲染

C# Blazor列表<;T>;更改T元素时缺少重新渲染,c#,blazor,C#,Blazor,当我从表单组件更新对象时,我尝试更新对象列表。但如果我的对象得到了很好的更新,我的列表就不会更新 这里是我的父组件 @inject ApiClient Api @if (normes != null) { <ul> @foreach (var item in normes) { <li @onclick="@(()=> norme = item)">@item.Name</l

当我从表单组件更新对象时,我尝试更新对象列表。但如果我的对象得到了很好的更新,我的列表就不会更新

这里是我的父组件

@inject ApiClient Api

@if (normes != null)
{
    <ul>
        @foreach (var item in normes)
        {
            <li @onclick="@(()=> norme = item)">@item.Name</li>
        }
    </ul>
}

@if (norme != null)
{
    <label>The bind parameter in the parent: @norme.Name</label>
    <Edit @bind-Norme="norme" />
}

@code {

    private List<Norme> normes { get; set; }

    private Norme norme { get; set; }

    protected override async Task OnInitializedAsync()
    {
        normes = await Api.GetAsync<List<Norme>>("norme");
    }
}
@InjectApiclient Api
@如果(正常值!=null)
{
    @foreach(标准中的变量项) { @item.Name }
} @if(norme!=null) { 父项中的bind参数:@norme.Name } @代码{ 私有列表规范{get;set;} 私有规范规范{get;set;} 受保护的重写异步任务OnInitializedAsync() { normes=await-Api.GetAsync(“norme”); } }
我从一个api获得一个列表,当我选择一个规范时,会显示一个表单组件来编辑它

这里是我的子组件:

@inject ApiClient Api

<Loader WaitFor="localNorme">
    <EditForm Model="localNorme" OnValidSubmit="OnValidSubmit">
        <DataAnnotationsValidator />
        
        @if (localNorme.Id == 0)
        {
            <h3>Nouvelle norme</h3>
        }
        else
        {
            <h3>Norme n° @localNorme.Id</h3>
        }

        <div class="btn-toolbar justify-content-end" role="toolbar">
            <div class="btn-group mr-2" role="group">
                <button type="submit" class="btn btn-outline-success"><i class="bi-save" /></button>
                <button type="button" class="btn btn-outline-danger" @onclick="OnCancelClick"><i class="bi-x" /></button>
            </div>
        </div>


        <div class="overflow-auto">

            <div class="form-group">
                <FormLabel For="@(()=>localNorme.Name)" />
                <InputText @bind-Value="localNorme.Name" class="form-control" />
                <ValidationMessage For="@(()=>localNorme.Name)" />
            </div>

            <input type="hidden" @bind-value="localNorme.Id" />
        </div>
    </EditForm>

    <label>The bind parameter in the child: @Norme.Name</label>
</Loader>


@code {
    [Parameter] public Norme Norme { get; set; }

    [Parameter] public EventCallback<Norme> NormeChanged { get; set; }

    private Norme localNorme;

    protected override async Task OnParametersSetAsync()
    {
        await LoadAsync();
    }

    private async Task LoadAsync()
    {
        if (Norme.Id > 0)
        {
            localNorme = await Api.GetAsync<Norme>($"norme/{Norme.Id}");
        }
        else
        {
            localNorme = new Norme();
        }
    }

    private async Task OnValidSubmit(EditContext context)
    {
        Norme model = context.Model as Norme;
        if (model.Id > 0)
        {
            // Update
            model = await Api.PutAsync<Norme>($"norme/{Norme.Id}", model);
        }
        else
        {
            // Create
            model = await Api.PostAsync<Norme>("norme", model);
        }
        await NormeChanged.InvokeAsync(model); // bound object update
    }

    private async Task OnCancelClick()
    {
        await LoadAsync();
    }
}
@InjectApiclient Api
@if(localNorme.Id==0)
{
新常态
}
其他的
{
Norme n°@localNorme.Id
}
子项中的bind参数:@Norme.Name
@代码{
[参数]公共规范规范{get;set;}
[参数]公共事件回调规范更改{get;set;}
私有规范本地规范;
受保护的重写异步任务OnParametersSetAsync()
{
等待LoadAsync();
}
专用异步任务LoadAsync()
{
如果(Norme.Id>0)
{
localNorme=await-Api.GetAsync($“norme/{norme.Id}”);
}
其他的
{
localNorme=新的Norme();
}
}
私有异步任务OnValidSubmit(EditContext上下文)
{
Norme model=context.model为Norme;
如果(model.Id>0)
{
//更新
model=wait Api.PutAsync($“norme/{norme.Id}”,model);
}
其他的
{
//创造
模型=等待Api.PostAsync(“标准”,模型);
}
wait NormeChanged.InvokeAsync(model);//绑定对象更新
}
专用异步任务OnCancelClick()
{
等待LoadAsync();
}
}
以下是我提交表格时的结果:

如您所见,我的列表没有更新

首先,在我的子组件中,我使用Norme参数作为表单中的模型。但我的父参数和列表在输入的OnChanged事件中更新。 因此,我在表单中插入一个localNorme作为模型,当它提交时,我使用EventCallback更新绑定参数。 在我的父级中,我的参数更新得很好,但我不知道启动列表更新时错过了什么

我尝试插入一些StateHasChanged(),但没有任何更改。如果我在父对象中更新了norme的属性,我还会检查列表是否已更新


谢谢。

我想您要更新的列表是“normes”

您可以在此处设置该列表:

受保护的重写异步任务OnInitializedAsync()
{
normes=await-Api.GetAsync(“norme”);
}
仅当父对象首次添加到渲染树时才调用

您需要一种在项目发生更改时更新它的方法

简单的方法是手动绑定Edit组件,这样就可以为NormeChanged回调注册一个处理程序

<Edit Norme="norme" NormeChanged=RefreshList/>

然后RefreshList可以更新列表“normes”并刷新父组件

@inject ApiClient Api

@if (normes != null)
{
    <ul>
        @foreach (var item in normes)
        {
            <li @onclick="@(()=> norme = item)">@item.Name</li>
        }
    </ul>
}

@if (norme != null)
{
    <label>The bind parameter in the parent: @norme.Name</label>
    <Edit @bind-Norme="norme" />
}

@code {

    private List<Norme> normes { get; set; }

    private Norme norme { get; set; }

    protected override async Task OnInitializedAsync()
    {
        normes = await Api.GetAsync<List<Norme>>("norme");
    }
}
异步任务刷新列表(Norme-Norme)
{
normes=await-Api.GetAsync(“norme”);
StateHasChanged();
}

当然,有很多方法可以做到这一点——集中式状态、事件聚合器、消息总线——这是最简单的方法。

我考虑过这个解决方案,您甚至不必将StateHasChanged()放在这里。它可以工作,但我感觉我对api进行了不必要的调用。我想没问题,但我会采取任何更优雅的解决方案;)谢谢(我会等几天再接受这个答案)哦,我明白了-很难理解这里的代码-我想我现在明白了-尝试向您呈现的列表项添加一个
@key
@item.Name
-它可能正在更新集合,但是不改变UI,因为它是如何检测变化的@key指令在这种情况下没有影响。但是我在回调中使用真实数据(大约10k个条目)尝试了api调用,并且响应时间几乎是即时的(我的列表显示在分页表中),因此我将使用此解决方案。非常感谢。