修改 Child 个组件之间的 Blazor 级联值

Modifiy Blazor Cascading Value between Child Components

我是 Blazor 的新手,正在尝试学习构建组件和页面的一些基础知识。现在我有一个如下所示的 MainLayout:

<CascadingValue Value="@layoutVals" Name="LayoutVals">
    <Leftbar />
    <div class="content-page">
        <Topbar />
        <div class="content">
            <div class="container-fluid">
                @Body
            </div>
        </div>
    </div>
</CascadingValue>
@code {
    public LayoutValues layoutVals = new LayoutValues()
    {
        Title = "Dashboard",
        Breadcrumbs = new Dictionary<string, string>()
        {
                { "Dashboard", "/" }
            }
    };
}

我正在尝试使用级联值来允许 child page/component 覆盖 Topbar 组件中的值(即页面标题、面包屑、我希望在整个过程中保持一致的其他一些显示值)浏览量,但根据页面动态替换)。

我能够访问 Topbar 组件中的 object 并且它们根据它们在 MainLayout 中初始化的内容进行了正确设置(如上所示),并且我能够在其中覆盖它们那个组件。但是,如果我将它们设置在页面中,更改似乎不会向上移动,然后沿着链返回到我希望显示它们的 Topbar 组件。

我确定我可以删除 Topbar 组件并在我的 MainLayout 中内联所有内容,但如果可能的话,我更愿意保持代码干净和独立。

您面临的问题是,在树下方的某些组件(页面、etx)中的值发生更改后,<Topbar /> 不会重新呈现。您必须告诉 Topbar 再次渲染:

public class LayoutValues
    {
        public string Title {get;set;}
        public Action ValuesChanged; 
    }

Topbar中订阅ValuesChanged

protected override void OnInitialized()
{
   LayoutVals.ValuesChanged += () => StateHasChanged();
  //dont forget to unsubscribe somewhere
}
[CascadingParameter] public LayoutValues LayoutVals {get;set;}

并在您更改值时调用它(或者您可以在 LayoutValues 的 setter 中执行此操作):

//some page
private void ButtonClicked()
{
 LayoutVals.Title="Changed title";
 LayoutVals.ValuesChanged.Invoke();

}
[CascadingParameter] public LayoutValues LayoutVals {get;set;}

Working demo.

此解决方案具有性能优势 - 应用程序无需重新渲染整棵树,只需 Topbar 调用了 StateHasChanged