Search code examples
inheritanceblazordatagridcolumnradzen

How can I convert a RenderFragment to a specific type?


I have a Blazor project with a custom component library based on Radzen components. One of the Radzen components I am using is RadzenDataGrid and I would like to reduce the amount of code that is currently required as I am using the component in different projects and the base is always the same. I created a custom component to replace RadzenDataGridColumn:

@* DataGridColumn.razor *@
@typeperam TItem;
@inherits RadzenDataGridColumn<TItem<;
<RadzenDataGridColumn TItme="TItem">
   <HeaderTemplate>
      <h1>@MyTitle</h1>
   </HeaderTemplate>
   @ChildContent
@code {
   [Parameter] public string MyTitle { get; set; }
   [Parameter] public RenderFragment ChildContent { get; set; }
}

@* Index.razor *@
...
<DataGridColumn MyTitle="Test" TItem="MyDataType" Property="Name">
   <Template Context="item">
      @item.Name
   </Template>
</DataGridColumn>

But I get the following error: Unrecognized child content inside component 'RadzenDataGridColumn'. The component 'RadzenDataGridColumn' accepts child content through the following top-level items: 'Columns', 'Template', 'EditTemplate', 'HeaderTemplate', ... However, I cannot put <Template> in DataGridColumn.razor because I need to access Context. Is there a way to cast the RenderFragment to type Template? Or to access Context inside the component? I'm still fairly new to Blazor, so please forgive me, if this is a trivial question.


Solution

  • Using inheritance

    additonal answer using inheritance. It turns out to be very simple too, but it may depend on how the RadzenDataGridColumn handles null and defaults.

    @* DataGridColumn.razor *@
    @typeperam TItem
    @inherits RadzenDataGridColumn<TItem>
    
    @* no other markup here, just call the baseclass *@
    @{ base.BuildRenderTree(__builder); }
    
    @code {
    
     [Parameter] public string MyTitle { get; set; }
    
     protected override void OnInitialized()
     {
        // this can be made conditional with an if()
        HeaderTemplate = @<h1>@MyTitle</h1>;
     }
    
    }
    

    It's a pity but you will need base.BuildRenderTree(__builder);, which is using a little behind-the-scenes magic. You can avoid base.BuildRenderTree() by inheriting in a normal .cs file instead of .razor. But then you can't write RenderFragments like @<h1>@MyTitle</h1>.

    All parameters are inherited so the pages could still supply a HeaderTemplate. Simply overwrite it or do some logic with is null.