radzenhq / radzen-blazor

Radzen Blazor is a set of 90+ free native Blazor UI components packed with DataGrid, Scheduler, Charts and robust theming including Material design and FluentUI.
https://www.radzen.com
MIT License
3.52k stars 785 forks source link

[RadzenDropDown] Data does not accept all types of IEnumerable #412

Closed rojait00 closed 2 years ago

rojait00 commented 2 years ago

Hi, I'm currently working on a website that lets you execute Regex.Replace(...). Therefore, I wanted to create a DropDown component (with multiple selection) containing the diferent RegexOptions(Enum). I described my first attempt in another Issue. I thought this was an issue with enums but it turned out that the documentation does not seem to be correct: “To display data in DropDown component you need to set collection of items (IEnumerable<>) to Data property. “

To Reproduce My first example usingRegexOptions[]:

<RadzenDropDown AllowClear="true" AllowFiltering="true" FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive"
                        Multiple="true" Placeholder="Select Regex Options..." 
                        @bind-Value=@selectedOptions Data=@regexOptions />
@code
{
    IEnumerable<RegexOptions> regexOptions = (RegexOptions[])Enum.GetValues(typeof(RegexOptions));
    IEnumerable<RegexOptions> selectedOptions = new List<RegexOptions>() { RegexOptions.IgnoreCase };
}

A more general example using IEnumerable<TestClass> generated via LINQ: (complete view)

<RadzenDropDown AllowClear="true" AllowFiltering="true" FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive"
                Placeholder="Select..." Multiple="true" Class="w-50"
                @bind-Value=@selectedValues Data=@data TextProperty="Name" ValueProperty="Value" />

@code
{
    IEnumerable<TestClass> data = GetData();
    IEnumerable<int> selectedValues = new[] { 3 };

    private static IEnumerable<TestClass> GetData()
    {
        var values = Enumerable.Range(1, 10);
        return values.Select(x => new TestClass("name" + x, x));
    }

    class TestClass
    {
        public TestClass(string name, int value)
        {
            Name = name;
            Value = value;
        }
        public string Name { get; private set; }
        public int Value { get; private set; }
    }
}

The second example leads to a strange behavior:

  1. The Value selected by default is 3 image
  2. The item is not visibly selected image
  3. After selecting “name1” it looks like this: image

There is also an error in the browser console:

crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Collection was modified; enumeration operation may not execute.
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at System.Collections.Generic.List`1.Enumerator[[System.Object, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNextRare()
   at System.Collections.Generic.List`1.Enumerator[[System.Object, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
   at System.Linq.Enumerable.SelectListIterator`2[[System.Object, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
   at System.Linq.Enumerable.<CastIterator>d__38`1[[System.Int32, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
   at Radzen.DropDownBase`1[[System.Collections.Generic.IEnumerable`1[[System.Int32, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].SelectItemFromValue(Object value)
   at Radzen.DropDownBase`1[[System.Collections.Generic.IEnumerable`1[[System.Int32, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].OnParametersSetAsync()
   at Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync()
   at Microsoft.AspNetCore.Components.ComponentBase.SetParametersAsync(ParameterView parameters)
   at Radzen.RadzenComponent.<>n__0(ParameterView parameters)
   at Radzen.RadzenComponent.SetParametersAsync(ParameterView parameters)
   at Radzen.DataBoundFormComponent`1.<SetParametersAsync>d__75[[System.Collections.Generic.IEnumerable`1[[System.Int32, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
   at Radzen.DropDownBase`1.<SetParametersAsync>d__78[[System.Collections.Generic.IEnumerable`1[[System.Int32, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
   at Radzen.Blazor.RadzenDropDown`1.<SetParametersAsync>d__21[[System.Collections.Generic.IEnumerable`1[[System.Int32, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()

But everything works fine if you change IEnumerable<TestClass> data = GetData(); To: IEnumerable<TestClass> data = GetData().ToList(); Also working: IEnumerable<TestClass> data = GetData().ToArray();

Expected behavior I expected the selection to be working for any type of IEnumerable.

Desktop OS: Win10 Browser Chrome Version 99 Radzen.Blazor 3.17.3

enchev commented 2 years ago

Plain IEnumerable will cause the component to be repopulated on every state change which might lead to exceptions and inability to keep various state related properties like selected item in this case. This is not limited to the DropDown component but it’s how Blazor components work.