I have a kind of factory in my application in which I create instances of various objects. All objects inherit from the same base class. I'm now trying to pass an instance of this derivation into a Component and would like to display the contents. I tried to implement this with a RenderFragment. This works for the initial view. However, the constructor of my derivation is called again by Blazor shortly afterwards and my instance in the html is a new one.
I need this to be able to react to interactions with my derivative. However, calling the constructor again leads to an instance which of course no longer contains any connections to my EventHandlers or the parameters that were originally given when the constructor was called.
ChildBase.cs
public class ChildBase : ComponentBase
{
public EventHandler? OnClick = null;
}
Child1.razor
@inherits ChildBase
<div style="width:100px; height: 200px; background:red;>
<button @onClick=OnClick>Click Child 1</button>
</div>
@code{
private async Task OnClick()
{
// do something
if(base.OnClick != null)
{
base.OnClick(this, EventArgs.Empty);
}
}
}
Child2.razor.cs
@inherits ChildBase
<div style="width:200px; height: 100px; background:yellow;>
<button @onClick=OnClick>Click Child 2</button>
</div>
@code{
private async Task OnClick()
{
// do something other
if(base.OnClick != null)
{
base.OnClick(this, EventArgs.Empty);
}
}
}
Page1.razor
<button @onClick="ShowChild1">One</button>
<button @onClick="ShowChild2">Two</button>
<br/>
<br/>
@if(ContentFragment != null)
{
@ContentFragment
}
@code{
private RenderFragment? ContentFragment;
private void ShowChild1()
{
ChildBase child = new Child1();
child.OnClick += OnChildClicked;
ContentFragment = createRenderFragment(child);
}
private void ShowChild2()
{
ChildBase child = new Child2();
child.OnClick += OnChildClicked;
ContentFragment = createRenderFragment(child);
}
private void OnChildClicked(object? sender, EventArgs e)
{
//Do something
}
private RenderFragment createRenderFragment(ChildBase child) => builder =>
{
builder.OpenComponent(0, child.GetType());
builder.CloseComponent();
};
}
Child1 and Child2 each have a completely different view and completely different content.
When you click on the respective button, you will see a double call with a breakpoint in the constructor of the respective child and child base. The component displayed in the view no longer has any connection to the ClickHandler.
Is there a way to create an instance of a component and dynamically give it to a, I'll call it, parent component and display it in the parent component?
You don't create Components, the Renderer does.
Here's a demo using your code showing how to build render fragments incorporating components:
ChildBaseusing anEventCallbackrather than aneventChild1[and Child2]There are several ways to put together the
RenderFragmentsto tell the Renderer how to build the content. This shows one.