I make multicultural site for web-shop with localization engine inside it. Almost each table with content has child table with localized texts. For example:
public class BlogTheme
{
[Key]
public int Id { get; set; }
[Required]
public string Key { get; set; }
public string Name { get; set; }
public List<BlogThemeCulture> BlogThemeCultures { get; }
}
public class BlogThemeCulture
{
[Required]
public int Id { get; set; }
[ForeignKey("Id")]
public BlogTheme BlogTheme { get; set; }
[Required]
[MaxLength(2)]
public string CultureId { get; set; }
[ForeignKey("CultureId")]
public Culture Culture { get; set; }
public string Name { get; set; }
}
I use Data Grids to edit main table together with culture values child table depending on culture which is allowed to user. To make it I should transform parent table and include child data. I tried to do it creating DataTable and ExpandoObject.
I added property to parent table:
[NotMapped]
public ExpandoObject Names { get; set; }
I created parent table with ExpandoObject included:
IEnumerable<BlogTheme> DataSource = await Db.BlogThemes.AsNoTracking().Include(c => c.BlogThemeCultures).OrderBy(r => r.Key).ToListAsync().ConfigureAwait(false);
foreach (BlogTheme item in DataSource)
{
item.Names = new ExpandoObject();
foreach (string culture in ServerStorage.InterpreterCultures)
{
item.Names.AddProperty(culture, item.BlogThemeCultures.Where(r => r.CultureId == culture).FirstOrDefault()?.Name);
}
}
And I tried to use it in Grid:
<SfGrid @ref="Grid" TValue="BlogTheme" Toolbar="@(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel", "Search", "ColumnChooser" })"
AllowSelection="true" AllowSorting="true" AllowFiltering="true" AllowPaging="true" AllowMultiSorting="true" AllowReordering="true" AllowResizing="true"
AllowTextWrap="true" EnableAutoFill="true" AllowExcelExport="true"
ShowColumnChooser="true"
ContextMenuItems="@(new List<object>() { "AutoFit", "AutoFitAll", "SortAscending", "SortDescending", "Copy", "Edit", "Delete",
"Save", "Cancel", "ExcelExport", "CsvExport", "FirstPage", "PrevPage", "LastPage", "NextPage"})"
AllowGrouping="false" AllowPdfExport="false">
<GridPageSettings PageSizes="true" />
<GridTextWrapSettings WrapMode="WrapMode.Content" />
<GridSelectionSettings Mode="Syncfusion.Blazor.Grids.SelectionMode.Row" Type="SelectionType.Multiple" />
<GridEvents TValue="BlogTheme" OnActionFailure="ActionFailure" OnActionComplete="ActionComplete" OnActionBegin="ActionBegin" DataBound="OnDataBound" />
@if (IsInitialRender)
{
<SfDataManager AdaptorInstance="@typeof(BlogThemeCRUD)" Adaptor="Adaptors.CustomAdaptor" />
}
<GridColumns>
<GridColumn Field="@nameof(BlogTheme.Id)" IsPrimaryKey="true" Visible="false" Type="ColumnType.Number" ShowInColumnChooser="false" />
<GridColumn Field="@nameof(BlogTheme.Key)" HeaderText="@(StringLocalizer["Key"])" Type="ColumnType.String" AllowEditing="@AllowAll" ShowInColumnChooser="false"/>
<GridColumn Field="@nameof(BlogTheme.Name)" HeaderText="@(StringLocalizer["Name"])" Type="ColumnType.String" AllowEditing="true" ShowInColumnChooser="false"/>
@foreach (Culture culture in ServerStorage.AllCultures)
{
if (ServerStorage.InterpreterCultures.Contains(culture.Id))
{
<GridColumn Field="@($"Names.{culture.Id}")" HeaderText="@culture.Name" Type="ColumnType.String">
<Template>
@(((context as BlogTheme).Names as IDictionary<string, object>)[culture.Id])
</Template>
</GridColumn>
}
}
<GridColumn Width="26px" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Center" ShowInColumnChooser="false">
<GridCommandColumns>
<GridCommandColumn ButtonOption="@(new CommandButtonOptions() { IconCss = "icon-new-tab", CssClass = "e-icon-button" })" Title="@(StringLocalizer["Show Theme Blog"])" />
</GridCommandColumns>
</GridColumn>
</GridColumns>
<GridSearchSettings IgnoreAccent="true" IgnoreCase="true" Operator="Operator.Contains" />
<GridFilterSettings Type="Syncfusion.Blazor.Grids.FilterType.Menu" ShowFilterBarStatus="true" EnableCaseSensitivity="false" IgnoreAccent="true" Mode="FilterBarMode.Immediate" />
<GridSortSettings>
<GridSortColumns>
<GridSortColumn Field="@nameof(BlogTheme.Key)" Direction="SortDirection.Ascending" />
</GridSortColumns>
</GridSortSettings>
<GridEditSettings Mode="EditMode.Normal" AllowAdding="@AllowAll" AllowDeleting="@AllowAll" AllowEditing="true"
AllowNextRowEdit="true" AllowEditOnDblClick="true" ShowDeleteConfirmDialog="true" />
</SfGrid>
The picture with result is included. I think something goes wrong with field binding <GridColumn Field="@($"Names.{culture.Id}")"...
Could you check my solution and offer any help with this mistake or any alternative decision to add lists, dictionaries or expandoobjects as complex data to grid?