从父组件如何使用foreach调用子组件方法

5

我看到过使用 @ref 属性从父组件调用子组件方法的示例,但是当我尝试在 foreach 循环中使用它时,只有最后一个呈现的组件方法被调用了,而不是所有的。下面是我的组件示例。

父组件:

<button type="button" class="btn btn-link" @onclick="BtnSyncAll_Click">Run<button>

@foreach(var site in Sites)
{
    <Site @ref="SiteView" @Code="@site"></Site>
}

@code {
    protected Site SiteView;
    protected List<string> Sites { get; set; } = new List<string>
    {
        "A00001",
        "A00002"
    };

    protected async Task BtnSyncAll_Click()
    {
        await SiteView.Sync();
    }
}

子组件(Site.razor):

<div>
    <p>@Code>/p>
</div>

@code {
    [Parameter]
    public string Code { get; set; }

    protected async Task Sync()
    {
        await ...
    }
}

你在哪里声明 Sites - Vencovsky
只有最后一个渲染的组件方法被调用,而不是所有组件的方法。你所说的“所有组件”,是指要调用所有Site组件的await SiteView.Sync()吗? - Vencovsky
@Vencovsky - 是的,我想要在foreach循环中从所有Site组件实例中调用SiteView.Sync()。我已经更新了我的问题并附上了Sites的声明。 - Jason Ayer
@Jason Ayer,我猜我的回答对你没有帮助,是吗?我应该删除它吗?没有声望的答案从来不会被用户阅读。除非它们符合首要前提——被接受,否则我从来不阅读答案。 - enet
@enet - 抱歉,我看到了,但还没有时间在我的应用程序中测试它。它看起来很有前途,请不要删除它。我会很快在这里测试并回复您。谢谢。 - Jason Ayer
请原谅我如果我错过了什么,但是我觉得同步方法最好用于父级来同步/更新子级参数。为什么不创建一个新的参数,初始值为null,然后在if(newParam!= null)的情况下覆盖(优先于)代码参数呢? - Jeff
2个回答

5

你和enet都过于复杂化了事情...

最“政治正确”的方法可能是创建一个独立的服务,在需要重新同步时向每个子组件发出信号,并通过 DI 进行注入,但这样做会花费太多精力,也许在你的情况下不值得。所以在这里提供一个更简单的方法:

首先,从你的组件中删除 Sync 方法,改为使用以下内容:

[Parameter]
public int SyncSignaler { get; set; }


protected override async Task OnParametersSetAsync()
{
    await Task.Delay(300);
    output = $"This is Site: {Code}";
    //StateHasChanged();
}

接下来,在你的父组件中声明一个整数变量,将其传递给子组件,并在每次需要刷新时递增。

在你的父组件中:

@foreach (var site in MySites)
{
    <Site Code="@site.Code" SyncSignaler="@syncIndicator"></Site>
}


@code {
 
    private int syncIndicator = 0;

    protected async Task BtnSyncAll_Click()
    {
        syncIndicator++;
        StateHasChanged();
    }

etc...

请告诉我它是否有效。干杯!


你知道吗,这实际上是我考虑使用的方法,但我认为肯定有一种简单的方法可以在循环中调用子组件的方法...但事实并非如此。这就是我要做的。谢谢。 - Jason Ayer
1
这绝对是最好的方法。致敬并感谢你。 - Lance Larsen - Microsoft MVP

1
这是一段描述应该如何做的代码示例:

Site.razor

<div>
    <p>@Code</p>
</div>
<p>@output</p>

@code {
    [Parameter]
    public string Code { get; set; }
    private string output;
    private static int index;

    public async Task Sync()
    {
        await Task.Delay(300);
        output = $"This is Site: {Code}";
        StateHasChanged();
    }
}

使用方法

<button type="button" class="btn btn-link" @onclick="BtnSyncAll_Click">Run</button>

@foreach (var site in MySites)
{

    <Site @ref="@site.SiteRef" Code="@site.Code"></Site>
}

@code {
     private List<MySite> MySites;

    protected override void OnInitialized()
    {
        MySites = new List<MySite> { new MySite { Code = "A00001", SiteRef = new Site() },
                                                 new MySite { Code = "A00002", SiteRef = new Site()} };
    }

    protected async Task BtnSyncAll_Click()
    {
        foreach (var site in MySites)
        {

            await site.SiteRef.Sync();
        }


    }

    public class MySite
    {
        public string Code { get; set; }
        public Site SiteRef { get; set; }
    }

希望这有所帮助…

你知道吗,我在想那可能是问题所在。任何通用集合项都可以使用吗,还是必须是 Site[] 项? - Jason Ayer
我刚意识到,我不知道如何用代码编写这个。我已经创建了 SiteView List<Site> 对象,但现在应该放入什么 @ref 呢? - Jason Ayer
我已经更新了我的答案。这个方法可以正常工作并且实现你想要的功能... 如果有问题请随时提问。 - enet
我很快会检查这个。 - Jason Ayer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接