简短的问题:是否存在渲染已实例化组件实例的方法?
我想有一个动态的内容对话框,内容应该使用组件类制作,它们也可能有自定义的属性、属性等。
我有以下Blazor结构,其中MainComponent
和Dialog
中的所有东西都是分离的,但可以使用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'不应设置在其组件之外