Blazor继承与ChildContent RenderFragments?

Blazor继承与ChildContent RenderFragments?,blazor,blazor-server-side,Blazor,Blazor Server Side,假设我们有一个基本组件ParentComponent.razor: <div id="ParentComponent">@ChildContent</div> @code { [Parameter] public RenderFragment ChildContent {get;set;} } @inherits ParentComponent <div id="ChildComponent">@Child

假设我们有一个基本组件
ParentComponent.razor

<div id="ParentComponent">@ChildContent</div>

@code {
    [Parameter] public RenderFragment ChildContent {get;set;}
}
@inherits ParentComponent

<div id="ChildComponent">@ChildContent</div>

@code {
    [Parameter] public RenderFragment ChildContent {get;set;}
}
有没有办法从ChildComponent填充ParentComponent的
@ChildContent
渲染片段

<ChildComponent>
    child content
</ChildComponent>
ChildElement.razor

@using Microsoft.AspNetCore.Components.Rendering;

@if (!HasRendered()) {
    SetRenderedStatus();
    <div id="ParentComponent">
        RenderChild(__builder);
    </div>
}

@code {
    protected bool _hasBaseRendered = false;

    protected bool HasRendered() {
        return _hasBaseRendered;
    }

    protected void SetRenderedStatus() {
         _hasBaseRendered = true;
    }

    protected virtual void RenderChild(RenderTreeBuilder __builder) { }
}
@using Microsoft.AspNetCore.Components.Rendering
@inherits ParentElement

@if (HasRendered()) {
    <div id="ChildComponent">
         @ChildContent
    </div>
}
@{
    base.BuildRenderTree(__builder);
}

@code {
    [Parameter] public RenderFragment ChildContent { get; set; }

    protected override void RenderChild(RenderTreeBuilder __builder) {
        this.BuildRenderTree(__builder);
    }
}
protected override void BuildRenderTree(RenderTreeBuilder __builder)
{
    if (HasRendered())
    {
        __builder.AddContent(0, "    ");
        __builder.OpenElement(1, "div");
        __builder.AddAttribute(2, "id", "ChildComponent");
        __builder.AddMarkupContent(3, "\r\n        ");
        __builder.AddContent(4, ChildContent);
        __builder.AddMarkupContent(5, "\r\n    ");
        __builder.CloseElement();
        __builder.AddMarkupContent(6, "\r\n");          
    }
    base.BuildRenderTree(__builder);
}
protected override void BuildRenderTree(RenderTreeBuilder __builder)
{
    if (!HasRendered())
    {
        SetRenderedStatus();
        __builder.AddContent(0, "        ");
        __builder.OpenElement(1, "div");
        __builder.AddAttribute(2, "id", "ParentComponent");
        __builder.AddMarkupContent(3, "\r\n");
        RenderChild(__builder);
        __builder.AddContent(4, "        ");
        __builder.CloseElement();
        __builder.AddMarkupContent(5, "\r\n");
    }
}
因此,当
hasprended
为false时,将忽略ChildContent,并指示它调用父类上的
base.BuildRenderTree

ParentElement.razor

@using Microsoft.AspNetCore.Components.Rendering;

@if (!HasRendered()) {
    SetRenderedStatus();
    <div id="ParentComponent">
        RenderChild(__builder);
    </div>
}

@code {
    protected bool _hasBaseRendered = false;

    protected bool HasRendered() {
        return _hasBaseRendered;
    }

    protected void SetRenderedStatus() {
         _hasBaseRendered = true;
    }

    protected virtual void RenderChild(RenderTreeBuilder __builder) { }
}
@using Microsoft.AspNetCore.Components.Rendering
@inherits ParentElement

@if (HasRendered()) {
    <div id="ChildComponent">
         @ChildContent
    </div>
}
@{
    base.BuildRenderTree(__builder);
}

@code {
    [Parameter] public RenderFragment ChildContent { get; set; }

    protected override void RenderChild(RenderTreeBuilder __builder) {
        this.BuildRenderTree(__builder);
    }
}
protected override void BuildRenderTree(RenderTreeBuilder __builder)
{
    if (HasRendered())
    {
        __builder.AddContent(0, "    ");
        __builder.OpenElement(1, "div");
        __builder.AddAttribute(2, "id", "ChildComponent");
        __builder.AddMarkupContent(3, "\r\n        ");
        __builder.AddContent(4, ChildContent);
        __builder.AddMarkupContent(5, "\r\n    ");
        __builder.CloseElement();
        __builder.AddMarkupContent(6, "\r\n");          
    }
    base.BuildRenderTree(__builder);
}
protected override void BuildRenderTree(RenderTreeBuilder __builder)
{
    if (!HasRendered())
    {
        SetRenderedStatus();
        __builder.AddContent(0, "        ");
        __builder.OpenElement(1, "div");
        __builder.AddAttribute(2, "id", "ParentComponent");
        __builder.AddMarkupContent(3, "\r\n");
        RenderChild(__builder);
        __builder.AddContent(4, "        ");
        __builder.CloseElement();
        __builder.AddMarkupContent(5, "\r\n");
    }
}
它呈现父标记,中途被定向到子级上覆盖的
RenderChild
,将流返回到子级,然后调用其
BuildRenderTree
hasprended
检查将确保避免无限循环,然后在返回到父级完成之前呈现标记的child部分


这可能是重构的,只是我目前正在进行的复制实验。

我刚刚在5.0RC2上测试了这一点

@inherits ParentComponent

<div id="ChildComponent">@ParentRenderFragment</div>

@code {

    RenderFragment ParentRenderFragment => builder =>
    {
        builder.OpenComponent<ParentComponent>(1);
        builder.AddAttribute(2, "ChildContent", this.ChildContent);
        // Additional inherited parameter's here
        builder.CloseComponent();
    };

}
@继承父组件
@ParentRenderFragment
@代码{
RenderFragment父级RenderFragment=>builder=>
{
OpenComponent(1);
builder.AddAttribute(2,“ChildContent”,this.ChildContent);
//这里有其他继承的参数
builder.CloseComponent();
};
}
制作了这个:

注: id不正确,因为它们作为renderfragment的一部分传递。如果您没有编辑子组件的权限,这可能需要dom操作来修复,因为您需要捕获属性或将id作为参数传递

不过,这显示了如何将父级原始渲染到子级。

复制并测试

ParentComponent.cs ChildComponent.cs
公共部分类ChildComponent:ParentComponent
{
受保护的覆盖void BuildRenderTree(RenderTreeBuilder)
{
OpenComponent(0);
builder.AddAttribute(1,“ChildContent”,(RenderFragment)((builder2)=>
{
建筑商2.开放部分(1,“部门”);
builder2.AddAttribute(2,“id”,“ChildComponent”);
builder2.AddContent(3,ChildContent);
builder2.CloseElement();
} ));
builder.CloseComponent();
}
}
剃刀索引
@page/“
子内容
public partial class ChildComponent : ParentComponent
{
    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        builder.OpenComponent<ParentComponent>(0);
        builder.AddAttribute(1, "ChildContent", (RenderFragment)((builder2) => 
       {
            builder2.OpenElement(1, "div");
            builder2.AddAttribute(2, "id", "ChildComponent");
            builder2.AddContent(3, ChildContent);
            builder2.CloseElement();
        } ));

        builder.CloseComponent();
    
    }
}
@page "/"

<ChildComponent>child content</ChildComponent>