I have a complicated issue when navigation through my Telerik-Blazor-Wizard. Every Time i want to navigate Back i get this Exception:
Error: System.InvalidOperationException: The render handle is already set. Cannot initialize a ComponentBase more than once.
at Microsoft.AspNetCore.Components.ComponentBase.Microsoft.AspNetCore.Components.IComponent.Attach(RenderHandle renderHandle)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.AttachAndInitComponent(IComponent component, Int32 parentComponentId)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateChildComponentOnFrame(RenderTreeFrame& frame, Int32 parentComponentId)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(DiffContext& diffContext, Int32 frameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(DiffContext& diffContext, Int32 frameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext& diffContext, Int32 newFrameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence(DiffContext& diffContext, Int32 oldFrameIndex, Int32 newFrameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer renderer, RenderBatchBuilder batchBuilder, Int32 componentId, ArrayRange`1 oldTree, ArrayRange`1 newTree)
at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
Note that I´m using a DynamicComponent to render my WizardPages..
@foreach( WizardSeite seite in WizardSeiten )
{
<WizardStep Label="@seite.Title" OnChange="@ReactOnChange">
<Content>
<DynamicComponent @ref="@currentPage" Type="@seite.GetType()" Parameters="@seite.Parameters"></DynamicComponent>
</Content>
</WizardStep>
}
and register the Pages in the ServiceCollection (IoC-Container)..
if( component.BaseType == typeof( WizardSeite ) )
{
// Registriere Wizardseite als Basetyp "WizardSeite"
services.AddTransient( component.BaseType ?? throw new NullReferenceException(), component );
}
If i Navigate back it tries to activate the component, I´m using a custom IComponentActivator that returns the registered Instance of my Wizard-Page.
instance = registeredPages.First( seite => seite.GetType() == componentType );
After that it seems that the component gets initialized twice thus throwing this error.
I know this issue is very specific any help to understand and/or resolve the problem is highly appreciated.
I found the issue!
Inside the IComponentActivator constructor i load the registered Pages once (into a list called registeredPages). The problem with this is that if the render tree gets refreshed it tries to initialize the component but gets the same instance of it. That leads to the exception above.
The solution: I register the components as Transiants thus every time i call GetService i get a new instance of the requested type. If i refresh registeredPages it always has a fresh component that can be initialized:
registeredPages = ServiceProvider.GetServices<WizardSeite>();
instance = registeredPages.First( seite => seite.GetType() == componentType );