Blazor-父组件中的上下文按钮由子组件更改

时间:2020-06-10 08:10:48

标签: data-binding blazor

当我刚接触Blazor时,我希望有人能提供帮助。

我已经开始了一个新的Blazor项目,并试图在顶部栏中添加上下文按钮,这些按钮可以根据子组件/进行更改(当您导航至第1页时,它可以显示与导航至时不同的内容。第2页)

enter image description here

这是我到目前为止的方法:

TopBar.razor -顶部栏的模板,带有渲染片段,因此我可以渲染其他内容

@inject Learning.Data.TopBarContext TopBarContext

<div class="col-sm-6">@Context</div>
<span class="col-sm-2">@Text1</span>
<span class="col-sm-2">@Text2</span>

@code {
    [Parameter]
    private RenderFragment Context { get; set; }

    [Parameter]
    public string Text1 { get; set; } = "Not Set";

    [Parameter]
    public string Text2 { get; set; } = "Not Set";    
}

MainLayout.razor -我使用TopBar并将其层叠到所有页面

@inherits LayoutComponentBase

<div class="sidebar">
    <NavMenu />
</div>

<div class="main">
    <div class="top-row px-4 auth">
        <TopBar />
    </div>

    <div class="content px-4">
        <CascadingValue Value="TopBar" Name="TopBar">
            @Body
        </CascadingValue>        
    </div>
</div>

@code {
    private TopBar TopBar;
}

现在我需要两个页面组件:

Page1.razor -在导航到时,将在顶部栏中呈现3个按钮

@page "/page1"

<button>One</button>
<button>Two</button>
<button>Three</button>

@code {

}

Page2.razor -在导航到时,将在顶部栏中显示2个按钮

@page "/page2"

<button>One</button>
<button>Two</button>

@code {

}

我知道我可以使用下面的代码来获取级联值:

[CascadingParameter(Name = "TopBar")]
    protected string TopBar { get; set; }

但不确定如何进行操作,我希望将整个组件层叠下来,以便在page1中可以做一些灵活的事情,例如:

<TopBar>
    <button>One</button>
    <button>Two</button>
    <button>Three</button>
</TopBar>

我可能会完全以错误的方式进行操作(我确实认为创建注册的单例可能是这样做的一种方式),但是您对如何实现此目的所做的任何澄清将不胜感激!

非常感谢

尼克

1 个答案:

答案 0 :(得分:0)

看看上面有什么,您差不多要在那里了。您可以像在MainLayout中将TopBar层叠起来一样,但是将其拿起的代码部分却让您失望。您已将级联值显示为字符串属性,但是请记住Blazor组件是已编译的,因此您需要将其列为类:

[CascadingParameter]
public TopBar Bar { get; set; }

这就是将其捕获到组件中的方式,然后您可以使用Bar.Context = // render fragment of your choice

这样的代码访问公共属性和方法来更新它们

这可能会有些棘手,因为您提供给Context属性的内容可能很难构建,因此最好让TopBar组件根据而是它拥有的数据结构。之前,我已经对Dictionary做过一些很好的链接,所以在您的TopBar中,您将拥有私有财产:

private Dictionary<string, string> LinkBodiesAndRefs { get; set; } = new Dictionary<string, string>();

此存储的链接文本作为键,目标URL作为每个记录的值, 然后渲染它们,如下所示:

TopBar.razor

@foreach (KeyValuePair<string, string> entry in LinkBodiesAndRefs)
{
    <a href="@entry.Value">@entry.Key</a>
}

然后在TopBar的@code块中,添加了一些与字典进行交互的方法:

TopBar.razor(续)

@code {

    private Dictionary<string, string> LinkBodiesAndRefs { get; set; } = new Dictionary<string, string>();

    public void AddLink(string linkBody, string linkDestination)
    {
        LinkBodiesAndRefs.Add(linkBody, linkDestination);
        StateHasChanged();
    }

    public void RemoveLink(string linkBody)
    {
        LinkBodiesAndRefs.Remove(linkBody);
        StateHasChanged();
    }

    public void Clear()
    {
        LinkBodiesAndRefs = new Dictionary<string, string>();
        StateHasChanged();
    }
}

然后在捕获级联TopBar的组件中,只需使用您希望的方法与数据结构进行交互,无论它是列表,字典还是其他任何东西:

Bar.AddLink("Products", "/products");

Bar.RemoveLink("Products");

如果对象列表需要进一步的交互,则可以对对象列表使用相同的方法,这些对象甚至可以是Razor组件,并且您的TopBar中可以有RenderFragment列表,如果需要的话可以将其渲染出来。关键是CascadingValue可以提供一个您可以定义其交互性的类,并且您可以使用各种诡计来使很酷的事情发生。

希望这会有所帮助,并且我现在还没有IDE的方便,所以上面的示例可能遗漏了一些语法。如果是这样的话,请提前抱歉。