Hi,
I have a large number of dynamically defined grids in my LOB application.
I have created a base Grid class and I use reflection to interrogate the properties of the base type of the grid and then formulate the GridColumns. It is effectively another implementation of the Syncfusion AutoGenerate columns function, but it gives me a lot of flexibility and consistency when creating a lot of grids.
However, there are some cases where I'd like to be able to dynamically define templates for the Grid Columns. In particular, for GridForeignKey columns, I'd like to be able to define multi-column combobox dropdowns programmatically, similar to the following links.
https://blazor.syncfusion.com/documentation/datagrid/editing#use-edit-template-in-foreign-key-column
https://www.syncfusion.com/blogs/post/easiest-way-to-create-a-multicolumn-combobox-in-blazor.aspx
The issue is that the syntax for defining the templates requires static definition of context type / referenced column etc., whereas I'd like to be able to generate this dynamically as text, which then gets interpreted and rendered.
I had a look at the new .Net6 dynamic component, but it didn't look like it could be used in this circumstance.
https://learn.microsoft.com/en-us/aspnet/core/blazor/components/dynamiccomponent?view=aspnetcore-6.0
Following is a code snippet from Grid.razor. Refer to the attached simplified sample app for a full working example.
<SfGrid TValue="TValue" DataSource="Items" Width="100%" Height="100%" AllowResizing="true" AllowReordering="true" Toolbar="@(new List<string>() { "Add", "Edit", "Delete", "Update","Cancel" })">
<GridEditSettings Mode="EditMode.Batch" AllowAdding="true" AllowEditing="true" ></GridEditSettings>
<GridSelectionSettings Mode="SelectionMode.Cell" CellSelectionMode="CellSelectionMode.Box" Type="SelectionType.Multiple"></GridSelectionSettings>
<GridColumns>
@foreach (var col in GetColumns())
{
@if (!col.IsForeignKey)
{
<GridColumn Field="@col.Field" HeaderText="@col.HeaderText" AutoFit="true" AllowReordering="true" AllowResizing="true" AllowEditing="true" IsPrimaryKey="@col.IsPrimaryKey"
></GridColumn>
}
else
{
Lookups.TryGetValue(@col.Field, out var lu);
<GridForeignColumn TValue="LookupDTO" Field="@col.Field" HeaderText="@col.HeaderText" AutoFit="true" AllowReordering="true" AllowResizing="true" AllowEditing="true" ForeignDataSource="@lu" ForeignKeyField="ID" ForeignKeyValue="Code">
@*HOW CAN I PROGRAMMATICALLY / DYNAMICALLY DEFINE EDIT TEMPLATE SIMILAR TO FOLLOWING*@
@* <EditTemplate>
<SfComboBox TValue="int?" TItem="LookupDTO" @bind-Value="@((context as typeof(TValue).Name)[email protected])" DataSource="@lu">
<ComboBoxFieldSettings Value="ID" Text="Code"></ComboBoxFieldSettings>
</SfComboBox>
</EditTemplate>*@
</GridForeignColumn>
}
}
</GridColumns>
</SfGrid>
Attachment: SyncfusionBlazorApp5GridMultiColumnLookup_fb843ed3.zip
Hi Greg,
Greetings from Syncfusion.
We are currently validating your query at our end and we will update further details within two business days on or before (26.09.2022). Until then we appreciate your patience.
Regards,
Monisha
Hi Greg,
Thanks for the patience.
We have checked your sample and modified your sample to render the multicolumn combobox. We have used value change event and you can customize the value as per your requirement in ValueChangeEvent . Kindly check the attached sample for your reference.
Please let us know if you have any concerns.
Regards,
Monisha
Thanks Monisha, That answer was worth waiting for! It is exactly what I needed.
Hi Monisha,
I made a slight change to the sample so that the ItemTemplate shows the values of the lookup list, rather than the statically calculated value from the parent context.
However, I can't work out how to bind the selected value in the combo box back to the parent grid. Do I need to do that in the event, or is there another way of implementing the binding?
<GridForeignColumn TValue="LookupDTO" Field="@col.Field" HeaderText="@col.HeaderText" AutoFit="true" AllowReordering="true" AllowResizing="true" AllowEditing="true" ForeignDataSource="@lu" ForeignKeyField="ID" ForeignKeyValue="Code">
<EditTemplate>
@{
var c = (context as TValue);
var a = c.GetType().GetProperty(col.Field).GetValue(c);
int? b = Convert.ToInt32(a);
//@bind-Value="@((context as typeof(TValue).Name)[email protected])"
@*HOW CAN I BIND THE SELECTED LookupDTO.ID TO THE BASE GRID FOREIGN KEY COLUMN? *@
<SfComboBox TValue="int?" Value="@b" TItem="LookupDTO" CssClass="e-multi-column" DataSource="@lu" PopupWidth="500px" PopupHeight="200">
<ComboBoxFieldSettings Value="ID" Text="Code"></ComboBoxFieldSettings>
<ComboBoxTemplates TItem="LookupDTO">
<HeaderTemplate>
<table ><tr><th style="width:100px">Code</th><th style="width:220px">Description</th></tr></table>
</HeaderTemplate>
<ItemTemplate Context="_context">
<table>
<tbody>
<tr>
<td style="width: 100px">@((_context as LookupDTO).Code) </td>
<td style="width: 220px">@((_context as LookupDTO).Description)</td>
</tr>
</tbody>
</table>
</ItemTemplate>
</ComboBoxTemplates>
<ComboBoxEvents TItem="LookupDTO" TValue="int?" ValueChange="@((args) => ValueChangeHandler(args, c))"></ComboBoxEvents>
</SfComboBox>
}
</EditTemplate>
</GridForeignColumn>
I worked it out. You do the update in the ChangeHandler. I just added another parameter to pull in the fieldname. Thanks for your help on this - it introduced me to some new concepts in Blazor.
private void ValueChangeHandler(ChangeEventArgs<int?, LookupDTO> args, TValue val, string FieldName)
{
val.GetType().GetProperty(FieldName).SetValue(val, args.ItemData.ID);
}
Hi Greg,
Welcome.
We are glad to hear that the provided solution was helpful at your end. Kindly get back to us if you have further queries. As always we will be happy to help you.
Regards,
Monisha