【问题标题】:Blazor components: How to communicate from grandchild to child to parent or grandchild to parentBlazor 组件:如何从孙子到孩子到父母或孙子到父母进行通信
【发布时间】:2023-04-18 16:58:01
【问题描述】:

在我的 Blazor 服务器应用程序中,我有一个名为 Home 的页面,它基本上是一个搜索页面。在主页(“父级”)上有一个带有控件的表单,用于过滤存储在后端数据库中的数据。搜索结果的每一行都有一个编辑按钮,该按钮显示一个引导对话框,允许编辑数据。 单击 UpdateDocumentNumber(孙)组件上的保存按钮后,我想刷新主页(父)中的搜索结果

  • 父级:带有搜索结果网格的主页(页面);为每个项目嵌入一个 DisplayDocumentNumber 组件
  • 子:DisplayDocumentNumber 组件,它有自己的(子)UpdateDocumentNumber 组件
  • 孙子:UpdateDocumentNumber 组件 - 引导对话框

我的理解是我可以使用事件回调来做到这一点;但是,虽然我可以从孙子向孩子提出/调用事件回调,但我似乎无法从孩子那里通知父母。

更多细节...

当主页(“父”页面)迭代返回的项目列表时,它会插入一个<DisplayDocumentNumber> 组件(“子”),然后<DisplayDocumentNumber> 组件有一个组件来引用“编辑”对话框。这是迭代搜索结果的主页:

<tbody>
    @foreach (var documentNumber in DocumentNumbers)
        {
            <DisplayDocumentNumber DocumentNumber="documentNumber" /> // DocumentNumber parameter in DisplayDocumentNumber receives the data from the documentNumber local var
        }
</tbody>

这是 DisplayDocumentNumber 组件:

public partial class DisplayDocumentNumber : ComponentBase
{
    [Parameter]
    public DocumentNumberDto DocumentNumber { get; set; }
    [Parameter]
    public EventCallback<bool> OnDocumentNumberUpdatedEventCallback { get; set; }
}

注意public EventCallback&lt;bool&gt; OnDocumentNumberUpdatedEventCallback { get; set; }。这在孙子之间正常工作。

在 DisplayDocumentNumber.razor 组件内部是为搜索结果中的每个文档编号呈现的行,包括一个具有 DOM 事件以显示引导对话框的“编辑”按钮。最后,如上所述,还有&lt;UpdateDocumentNumberDialog&gt; 组件,即

<tr>
    <td>@DocumentNumber.Column1Name</td>
    <td>@DocumentNumber.Column2Name</td>
    ...etc
    <td><button class="btn btn-primary table-btn" @onclick="@(() => ShowEditDocumentNumberDialog(DocumentNumber))">Edit</button></td>
    <UpdateDocumentNumberDialog @ref="UpdateDocNumDialog" DocumentNumberForUpdating="DocumentNumber" DocumentNumberUpdatedEventCallback="@UpdateDocumentNumberDialog_OnDialogClose"></UpdateDocumentNumberDialog>
</tr>

如果事件回调仅适用于孙子到子或子到父,我是否必须按照 Chris Sainty (https://chrissainty.com/3-ways-to-communicate-between-components-in-blazor/) 的描述创建某种 状态容器?或者,我是否遗漏了有关事件回调的某些内容?我试图消除子组件,但失败了,因为编辑按钮总是显示网格中迭代的最后一项。

【问题讨论】:

  • CascadingValues 就是这样,级联的。您可以在父组件上定义一个回调(例如,OnDocumentNumberUpdatedEventCallback),并将父组件向下级联到孙组件,孙组件可以在父组件上调用回调。
  • 到目前为止,我还没有让这个工作,所以我错过了一些东西。虽然继续这一努力。谢谢!
  • 你的解释很好,但我需要&lt;CascadingValue Value="this"&gt;,特别是@Bennyboy1973 提供的Value="this" 部分。我有更多关于使用“this”的知识。再次感谢!
  • 传递 Value="this" 也包含在您发布的 Chris Sainty 的博客文章中。可能值得再读一遍。

标签: events callback components blazor communication


【解决方案1】:

我能想到几个选项。一种是让孙子访问主页。这根本不需要事件:

Parent.razor

<CascadingValue Value="this">
    Body of page, somewhere in there including <Grandchild/>
</CascadingValue>

@code{
    async Task DoSomething(){
    }
}

Grandchild.razor

@code {
    [CascadingParameter]
    public Parent MainPage {get; set;} // Or whatever your main page is called

    async Task StartSomething (){
        if (MainPage is not null) MainPage.DoSomething();
    }
}

【讨论】:

  • 如果您不想使用服务,这是迄今为止最简单的。
【解决方案2】:

我在 Child 和 Grandchild 组件中包含以下参数:

 [Parameter]
    public Action MyDataHasChanged {get;set;}

进一步,在我的孙子组件中:

@code
{
  public void RefreshMySearchResultsInParent()
  {
      MyDataHasChanged?.Invoke();
  }
}

在我的子组件中:

<Grandchild @MyDataHasChanged="MyDataHasChanged"></Grandhild>

在我的父组件内部:

<Child @MyDataHasChanged="RefreshMySearchResults"></Child>



 @code
    {
    
    public void RefreshMySearchResults()
    {
       //Do this...
    }

}

【讨论】:

  • 我几乎是这样做的,只是我将事件放在一个类中,该类会注入到任何需要它的页面中。
  • 绝妙的想法@danielSnyder - 这也将使维护变得更加容易?
  • 谢谢。我将整体模式 SWIMMER I 称为存储库、事件、模型和模板的注入。 (模板的内容来自数据库)它还允许对页面更改通知进行精细控制。用途是创建一个工具来开发 Blazor 单页应用程序。总有一天我会建造它
  • 而且我现在被禁止提问,所以如果我很聪明,我想我不会再有了。
最近更新 更多