动态呈现Blazor中具有属性值的未知组件实例(不是子级/父级)



简短的问题:是否存在渲染已实例化组件实例的方法?

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


我有以下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
}

只要我在那里传递一个"普通"组件,这就可以了,然而,我想要一些动态文本,例如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。是否可以使用实例而不仅仅是组件类名?

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

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",
};

组件参数'Title'不应设置在其组件之外

相关内容

  • 没有找到相关文章

最新更新