在 Blazor 中动态呈现具有 属性 值的未知组件实例(不是 child/parent)?

Dynamically render an unknown component instance with property values in Blazor (not child/parent)?

简短的问题:有没有渲染一个已经实例化的组件实例?

我想要一个动态内容对话框,内容应该使用组件制作class,它们也可能有自定义属性、属性等


我有以下 Blazor 结构,其中 MainComponentDialog 中的所有内容都是分开的,但可以使用 IDialogService:

相互联系
<main>
    <MainComponent />
</main>

<Dialog />

但是,我希望 Dialog.razor 中的内容是动态的,所以我尝试这样做:

<dialog data-active="@(this.IsShowing)">
    <dialog-cover></dialog-cover>

    <dialog-container>
        @if (this.contentFragment != null)
        {
            @(this.contentFragment)
        }
    </dialog-container>
</dialog>

@code {

    RenderFragment contentFragment { get; set; }

    internal void SetFragments(ComponentBase dialog)
    {
        this.contentFragment = builder =>
        {
            builder.OpenComponent(0, dialog.GetType());
            builder.CloseComponent();
        };

        this.StateHasChanged();
    }

    // Other logic code for showing/hiding etc

}

只要我在那里传递一个 "plain" 组件就可以工作,但是,我想要一些动态文本,例如 ConfirmDialog.razor:

@if (this.Title != null)
{
    <header>
        <h2>@(this.Title)</h2>
    </header>
}

@if (this.Text != null)
{
    <main>
        @(this.Text)
    </main>
}

@code {

    public string Title { get; set; }
    public string Text { get; set; }

}

用法:

    var diagConfirm = new ConfirmDialog()
    {
        Title = "Please confirm!",
        Text = "Something good happened!",
    };

    var result = await this.dialogService.ShowAsync(diagConfirm);

但是,使用该片段,会创建一个新的 ConfirmDialog 实例,而不使用 diagConfirm。无论如何要使用实例而不只是组件 class 名称?

这是我目前使用的临时解决方案。我知道这是一个 hack,不应该是一个正确的答案,但它现在有效。

        var properties = component.GetType().GetProperties();

        RenderFragment fragment = builder =>
        {
            builder.OpenComponent(0, component.GetType());

            foreach (var property in properties)
            {
                if (property.GetCustomAttribute<ParameterAttribute>() == null)
                {
                    continue;
                }

                var value = property.GetValue(component);

                builder.AddAttribute(0, property.Name, value);
            }

            builder.CloseComponent();
        };

基本上,我使用反射将具有Parameter的所有属性复制到新创建的组件中。这需要组件属性附加 [Parameter] 属性。

你也会在这些行收到来自 VS 的警告,但如果你知道自己在做什么,你可以安全地忽略它们。

    var diagConfirm = new LConfirmDialog()
    {
        Title = "Title",
        Text = "Hello",
    };

Component parameter 'Title' should not be set outside of its component