Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
632 views
in Technique[技术] by (71.8m points)

c# - How to render multiple child components in parent component without calling @ChildContent in Blazor


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Component Instances

Components are classes, and you need an instance of a Component class to be created before you can access its members - such as its ChildContent.

The Component instance is created by Blazor when it is first rendered.

In order to render the Child Component(s), they need to be part of a RenderTree batch.

If the Component (Parent) that "owns" the RenderFragment (Parent.ChildContent) containing the Child Component does not itself render that ChildContent, then the Child Component(s) instance will not get created.

A line of code like this is accessing an instance Property of the Child Component, and this requires the Child Component instance to exist prior to being called.

@lChild.ChildContent(lData); // We render the child here

So, in short, you need to render ChildContent in your Parent Component to create the instances of the Child Components and register them in the RenderTree.

Slight Variation

If your Child Component really has no internal logic - as in the example in your question - then it does not need to be a Component at all - it can be a RenderFragment, which then makes your requirement to wrap each child in extra markup much easier, as a RenderFragment does not get instantiated like a Component.

Multi-child RenderFragments

If you write your Parent to accept multiple child RenderFragments, like this:

@typeparam TData

<div class="parent-component">
  @foreach (var lData in DataSource)
    {
        @foreach (var lChild in m_Children)
        {
            <div class="child-component">
                @lChild(lData);
            </div>
        }
    }

</div>

@code {
    [Parameter]
    public List<TData> DataSource { get; set; }

    [Parameter]
    public RenderFragment<TData> ChildFragment { set => m_Children.Add(value); }

    /// Collection of all added child fragments
    private List<RenderFragment<TData>> m_Children = new List<RenderFragment<TData>>();
}

You can use it like this:

<ParentComponent DataSource="@AccountList">
    <ChildFragment><span>@context.FirstName</span></ChildFragment>
    <ChildFragment><i>@context.LastName</i></ChildFragment>
    <ChildFragment><b>@context.Age</b></ChildFragment>
</ParentComponent>

As an added bonus, you no longer need to specify the type for TData as it can be inferred.

** Note: This technique will only work for RenderFragments, but you can, of course put any content you like inside the ChildFragment(s), including Child Components and still have control over the output rendering.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...