在 Blazor 中动态呈现具有 属性 值的未知组件实例(不是 child/parent)?
Dynamically render an unknown component instance with property values in Blazor (not child/parent)?
简短的问题:有没有渲染一个已经实例化的组件实例?
我想要一个动态内容对话框,内容应该使用组件制作class,它们也可能有自定义属性、属性等
我有以下 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
}
只要我在那里传递一个 "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
简短的问题:有没有渲染一个已经实例化的组件实例?
我想要一个动态内容对话框,内容应该使用组件制作class,它们也可能有自定义属性、属性等
我有以下 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
}
只要我在那里传递一个 "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