Search code examples
c#asp.netlinqblazor

LINQ query for binding to specific values in a collection of ints


I'm trying to dynamically build dropdown lists within my Blazor form component by using a foreach statement. The form is for a product and a product can be linked to tags. Tags themselves have a tag type and I want to dynamically generate a separate dropdown for each tag type which pulls through all the tags linked to that type and only binds to tags of that tag type.

@foreach (var type in tagTypesDto)
{
    <div class="form-group mb-3">
        <RadzenSelect AllowClear="true" AllowFiltering="true" @[email protected](x => x == type.Tags.Select(x => x.Id).FirstOrDefault()) Multiple="true" Placeholder="@_localizer["PleaseSelect"]" [email protected](x => x.TagTypeId == type.Id)
            TextProperty="Name" ValueProperty="Id" Label="@_localizer["ProductAttributes"]" />
    </div>
}

I'm unable to get this to build because I'm getting the following error:

The left-hand side of an assignment must be a variable, property or indexer

I think the issue is the LINQ query I'm trying to pass it for @bind-Value - if I replace this with just @productDto.SelectedProductTags then it builds and generates a separate dropdown for each tag type, but if I try and select any tags it fails, presumably because it doesn't know which dropdown to assign the tag to.

SelectedProductTags looks like this in my product model:

public virtual IEnumerable<int>? SelectedProductTags { get; set; } = new int[] { };

I'm using .NET 6 and Blazor Webassembly.


Solution

  • I created a demo project on GitHub with a possible solution to your problem: https://github.com/Jimmys20/SO74219635

    You have to use manual event binding:

    @foreach (var type in tagTypesDto)
    {
        <div class="form-group mb-3">
            var tagTypeId = type.Id;
        
            <RadzenDropDown Data="tagsDto.Where(x => x.TagTypeId == type.Id).ToList()"
                            Value="productDto.SelectedProductTags"
                            ValueChanged="values => OnValueChanged(values, tagTypeId)"
                            TValue="List<int>"
                            Multiple="true"
                            ValueProperty="Id"
                            TextProperty="Name" />
        </div>
    }
    
    @code {
        private void OnValueChanged(List<int> values, int tagTypeId)
        {
            var data = tagsDto.Where(t => t.TagTypeId == tagTypeId).Select(t => t.Id);
            
            productDto.SelectedProductTags.RemoveAll(x => data.Contains(x));
            
            productDto.SelectedProductTags = productDto.SelectedProductTags.Concat(values).ToList();
        }
    }
    

    SelectedProductTags needs to be changed to List<int>.