DataGrid binding column to list

I'm trying to get a one-to-many relationship working in a RadzenDataGrid where the user can select multiple items from a drop down box in the edit template, but I'm running into difficulties because I'm using Entity Framework Core and the underlying relationship is an ICollectible and RadzenDataGrid doesn't seem to be able to bind to this, it has to be an IEnumerable<>, at least by default. Here's the setup:

DataGrid Column:

                            <RadzenDataGridColumn TItem="SyllabusItem" Property="PreRequisites" Title="Pre-Requisites">
                                <Template Context="syllabusItem">
                                    @if (syllabusItem != null && syllabusItem.PreRequisites != null)
                                    {
                                        <RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Normal" JustifyContent="JustifyContent.Normal">
                                            @foreach (SyllabusItem item in syllabusItem.PreRequisites)
                                            {
                                                <RadzenText>@item.Name</RadzenText>
                                            }
                                        </RadzenStack>
                                    }
                                </Template>
                                <EditTemplate Context="syllabusItem">
                                    <RadzenDropDown style="display: block; width: 100%" @bind-Value="@syllabusItem.PreRequisites" Name="Pre-Requisites" TextProperty="Name"
                                                    Multiple="true" AllowClear="true" MaxSelectedLabels="2" Placeholder="Select Pre-requisite(s)"
                                                    Data="@syllabusItems?.Where(x => x.Name != syllabusItem.Name)" />
                                </EditTemplate>
                            </RadzenDataGridColumn>

Entity:

    public class SyllabusItem : BaseCTSSEntity
    {

// Other fields omitted for brevity

        [Comment("Syllabus items required before this item can be completed")]
        public virtual ICollection<SyllabusItem> PreRequisites { get; set; }


    }

With Entity Framework Core ICollection is the best way to create the relationship, but because it's an ICollection instead of an IEnumerable I get this error:

2023-03-17T15:07:52.168Z] Error: System.InvalidCastException: Unable to cast object of type 'System.Linq.EnumerableQuery`1[CTSS.Data.Model.SyllabusItem]' to type 'System.Collections.Generic.ICollection`1[CTSS.Data.Model.SyllabusItem]'.
   at Radzen.DropDownBase`1.SelectItem(Object item, Boolean raiseChange)
   at Radzen.Blazor.RadzenDropDown`1.OnSelectItem(Object item, Boolean isFromKey)
   at Radzen.Blazor.RadzenDropDown`1.OnSelectItemInternal(Object item, Boolean isFromKey)
   at Radzen.Blazor.RadzenDropDownItem`1.SelectItem(MouseEventArgs args, Boolean isclick)
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)

Is there a way to get this to bind to an ICollection instead of an IEnumerable? Or do I need to do a lot of work in the code behind to have a separate IEnumerable that on row update I save to the proper ICollection?

Thanks,

Geoff

Thanks for the report @gpankretz! We will do our best to provide fix for this in our next update Monday!

1 Like

Tried it out with the release today and it appears to work great with an ICollection. Thank you very much!

I'm trying now to convert the above setup to a many-to-many relationship where I have a mapping table now. How do I get this dropdown setup to work where I can select another "SyllabusItem" and have it map to the pre-requisite to a new instance of the mapping class and the context "SyllabusItem" map to the syllabusItem in the context?

Everything else in the above setup is pretty easy to convert to display the list of mapped pre-requisites, but I can't figure out how to get this multi-select dropdown setup to work w/ the map class.

Here's the mapping class:

    public class PreRequisiteMap
    {
        public long SyllabusItemId { get; set; }
        public SyllabusItem SyllabusItem { get; set; }

        public long PreRequisiteId { get; set; }
        public SyllabusItem PreRequisite { get; set; }
    }

I have a few situations in the app where I will be having many-to-many relationships like this, and I'm just not seeing how to do this in Blazor. I see some similar examples in your Angular setups, but not sure how to fully translate this into doing it in Blazor.

Thanks for any help you can provide!

Geoff

There are several good examples of many-to-many relationships in Northwind database - EmployeeTerritories, Order Details, etc. You can check what code will be generated by Radzen IDE / Radzen Blazor Studio for reference:

Call me crazy, but I found a github repo for the demos you have on the website, but not for the northwind stuff... what am I missing? Can you provide a link to the repo?

Thanks!

You don’t need any repo, just download Radzen Blazor Studio and scaffold CRUD pages from Northwind - all of these in less than 5 minutes.

1 Like

Got it. Thanks for the replies.

After digging through those examples I don't see any that really match the use case I'm looking at. Those all have their separate CRUD pages for each of the many-to-many relationships. I'm trying to do something a bit different than that and I can't quite figure it out.

Hopefully, this description is a bit more clear. :slight_smile:

My top level table is a "Syllabus", when I expand that row, it shows a list of "SyllabusItems". What I'm trying to do is get it so that when I edit a "SyllabusItem" row (in-line edit) that the DropDown for PreRequisites shows a list of other "SyllabusItems" on the same "Syllabus". However, I need to map the selected items in the dropdown to a new "PreRequisiteMap" where the "Syllabus" in the Context is mapped to one field and the "SelectedItem" in the DropDown value(s) selected are set to a different field in the "PreRequisiteMap" object.

Currently, I have it where it loads the data in the drop down and if I handle the Change call, I can set the PreRequisiteMap(s) properly. Here's the pertinent parts my code:

<RadzenDataGrid @ref="syllabiGrid" Data="@syllabi" TItem="Syllabus" RowExpand=@GetChildData SelectionMode="DataGridSelectionMode.Single" ExpandMode="DataGridExpandMode.Single">
    <Template Context="syllabus">
        <RadzenDataGrid @ref="syllabusItemsGrid" Data="@syllabusItems" TItem="SyllabusItem" EditMode="DataGridEditMode.Single">
            <Columns>
                 <RadzenDataGridColumn TItem="SyllabusItem" Property="PreRequisites" Title="Pre-Requisites">
                        <Template Context="syllabusItem">
                            @if (syllabusItem != null && syllabusItem.PreRequisites != null)
                            {
                                <RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Normal" JustifyContent="JustifyContent.Normal">
                                    @foreach (PreRequisiteMap map in syllabusItem.PreRequisites)
                                    {
                                        <RadzenText>@map?.PreRequisite?.Name</RadzenText>
                                    }
                                </RadzenStack>
                            }
                        </Template>
                        <EditTemplate Context="syllabusItem">
                           <RadzenDropDown TValue="SyllabusItem" style="display: block; width: 100%"  Name="Pre-Requisites" TextProperty="Name"
                                           FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive" FilterOperator="StringFilterOperator.StartsWith" AllowFiltering="true"
                                           Multiple="true" AllowClear="true" MaxSelectedLabels="2" Placeholder="Select Pre-requisite(s)" Change="(args=> PreRequisitesChanged(args, syllabusItem))"
                                           Data="@syllabusItems?.Where(x => x.Name != syllabusItem.Name)" />
                        </EditTemplate>
                    </RadzenDataGridColumn>
            </Columns>
    </Template>

// In the code behind:
    protected void PreRequisitesChanged(object args, SyllabusItem activeSyllabusItem)
    {
        IEnumerable<SyllabusItem> preRequisites = (IEnumerable<SyllabusItem>)args;
        SyllabusService.UpdatePreRequisites(preRequisites, activeSyllabusItem);
    }

For the most part it's working. When I select the PreRequisite in edit mode I get the list I want and I can select items:

However, after I save these items and reopen for edit the "saved" PreRequisites don't show selected.

I apologize for all the questions. I'm extremely new to Blazor and this setup, and I'm likely doing something fundamentally wrong or missing something completely. I'm guessing it's how I'm binding stuff, but not fully sure.

Thanks for any help anyone can provide.