Blazor 将上下文传递给 RenderFragment

Blazor pass context to RenderFragment

所以,我有一个包含网格的页面

SearchPage.razor

<FiGrid @ref="Grid"
    <Columns>
        @Columns
    </Columns>
    <EditFormTemplate Context="contextEntity">
        @EditFormTemplate(contextEntity)
    </EditFormTemplate>
</FiGrid>

@code{
protected RenderFragment Columns { get; set; }

protected RenderFragment<object> EditFormTemplate { get; set; }
}

此页面有一个用于呈现列的 RenderFragment 和一个用于在必要时呈现 editForm 的 RenderFragment

我继承自此 SearchPage 以自定义这 2 个道具:

自定义SearchPage.razor

@inherits SearchPage

@{
    base.BuildRenderTree(__builder);
}

@code {

    private static RenderFragment _customColumns = __builder =>
    {
        <CustomColumn FieldName="@nameof(Factory.Id)" Width="75px"/>
        <CustomColumn FieldName="@nameof(Factory.BusinessName)"/>
        <CustomColumn FieldName="@nameof(Factory.Address)"/>
    };

    private static RenderFragment<object> _customEditFormTemplate = editModel => __builder =>
    {
        <CustomEditForm Entity="editModel"/>;
    };

    protected override void OnInitialized()
    {
        Columns = _customColumns;
        EditFormTemplate = _customEditFormTemplate;
        base.OnInitialized();
    }

}

但它在控制台上给我这个错误:

Operation is not valid due to the current state of the object.

可能我用错了方法,那样的话,我应该如何完成同样的事情?

我需要能够从页面继承并向页面传递采用模板上下文的自定义编辑表单

基本上我想将模板的上下文传递给通过代码创建的 RenderFragment

您收到错误是因为您无法按照您设想的方式构建组件继承。你不能像这样手动调用 BuildRenderTree:

base.BuildRenderTree(__builder);

因为您没有对 Renderer 的 RenderTreeBuilder.

的引用

A RenderFragment 是一个委托,定义为:

public delegate void RenderFragment(RenderTreeBuilder builder);

它是由 Renderer 调用它并传入 RenderTreeBuilder.

的渲染器实例的 运行

所有 Razor 页面都 pre-compiled 到 C# 类。所以这个简单的组件 DisplayDiv.razor:

<h3>@Header</h3>

@code {
    [Parameter] public string Header { get; set; } = "Hello Blazor";
}

Razor 处理器将 pre-compiled 变成这样的东西:

public class DisplayDiv : ComponentBase
{
    [Parameter] public string Header { get; set; } = "Hello Blazor";

    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        builder.OpenElement(0, "h3");
        builder.AddContent(1, this.Header);
        builder.CloseElement();
    }
}

BuildRenderTree 被添加到 ComponentBase 的基础 RenderFragment 中,StateHasChanged 在调用渲染器渲染组件时将其传递给渲染器。

private readonly RenderFragment _renderFragment;

public ComponentBase()
{
    _renderFragment = builder =>
    {
        _hasPendingQueuedRender = false;
        _hasNeverRendered = false;
        BuildRenderTree(builder);
    };
}

您正在尝试定义 BuildRenderTree 的多个副本,这在剃刀页面设置中是无法做到的。 Razor pre-compiler 构建的子 BuildRenderTree 方法覆盖了父方法。

您的 SearchPage 是您随后在页面中使用的组件

<SearchPage>
    <Columns>
        <CustomColumn FieldName="@nameof(Factory.Id)" Width="75px"/>
        <CustomColumn FieldName="@nameof(Factory.BusinessName)"/>
        <CustomColumn FieldName="@nameof(Factory.Address)"/>
    </Columns>
    <EditFormTemplate>
        <CustomEditForm Entity="editModel"/>
    </EditFormTemplate>
</SearchPage>

您可以在组件中进行继承,但您的父组件必须是 类,而不是 Razor 组件,并直接在代码中构建任何标记。