RadzenListBox, bug when using asynchronous call LoadData

@enchev

Thank you for your time this is really great.
Let me try to explain it again:

The select all checkbox refers to the current dataset.
When the second dataset is loaded, select all should be deselected to select the next dataset completely.

As you can see in your video, the select all checkbox is not always deselected when loading a new record.

The first seconds of your video it works fine and then not anymore.
So the rule should be:
When new items are loaded and not selected the select all checkbox must be deselected.

I hope I could explain this somehow :face_with_monocle: :wink:

Or have I not understood the control correctly?
Then it would be nice if you could explain it to me.

-Tom

I see now. We will do our best to improve this in one of our next updates.

1 Like

It will be part of our next update early next week:

@enchev

This is fantastic, thank you very much.

-tom

@enchev

I have tested the listbox from the current master branch.
I would also like to say it is great, your fix cycles are incredibly fast. :ok_hand:t3:

Unfortunately there is still a probelm.

Explanation:
Depending on the height of the ListBox there is a maximum number of items. For example at 400px height I have a maximum of 19 items that are rendered. If I have 19 items selected the condition is always true.

//Method
internal bool IsAllSelected()
...
//line
(View != null && selectedItems.Count == View.Cast<object>().Count())

The select all checkbox is no longer deselected when I scroll down.

I have reached the maximum number of selection, depending on the height. The height is not important. If the number of my entire list is greater than the maximum number of rendered items, the error occurs.

I hope I could explain this :face_with_monocle:

-Tom

I’m afraid that this is the best we can do. Calculating if this checkbox should be checked or not depending on height is close to impossible. Still if you find a better solution you can submit pull request.

@enchev

Hello Enchev,
I have explained myself wrongly.

You must be very tired of this topic, I know.

But please take your time again.

First of all, I don't know your library enough to create a pull request.

I have prepared something:

The current behavior of the ListBox (Master branch)
Animation

This behaves somehow wrong
Then I changed two methods for tests.

-SelectAll()
-IsAllSelected()

Animation2

Now the list box behaves correctly for me.
I think my quick changes only make sense if it has AllowVirtualization set to true.
I use a list of the type string with a unique identifier for the tests.

SelectAll()

 protected async System.Threading.Tasks.Task SelectAll()
        {
            if (Disabled)
            {
                return;
            }

            var count = default(int);
#if NET5
            count = Count;
#endif

            //if (selectedItems.Count != View.Cast<object>().Count())
            if (selectedItems.Count != count)
            {
                View.Cast<object>().ToList().ForEach(item =>
                {
                    if (!selectedItems.Contains(item))
                    {
                        selectedItems.Add(item);
                    }
                });

                //selectedItems.Clear();
                //selectedItems = View.Cast<object>().ToList();
            }
            else
            {
                selectedItems.Clear();
            }

            if (!string.IsNullOrEmpty(ValueProperty))
            {
                System.Reflection.PropertyInfo pi = PropertyAccess.GetElementType(Data.GetType()).GetProperty(ValueProperty);
                internalValue = selectedItems.Select(i => PropertyAccess.GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
            }
            else
            {
                var type = typeof(T).IsGenericType ? typeof(T).GetGenericArguments()[0] : typeof(T);
                internalValue = selectedItems.AsQueryable().Cast(type);
            }

            await ValueChanged.InvokeAsync((T)internalValue);
            if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
            await Change.InvokeAsync(internalValue);

            StateHasChanged();
        }
  • Notice:
    When using complex classes with ValueProperty, the contains check of the list must be modified.

IsAllSelected()

 internal bool IsAllSelected()
        {
            var count = default(int);
#if NET5
            count = Count;
#endif

            if (LoadData.HasDelegate && !string.IsNullOrEmpty(ValueProperty))
            {
                return View != null && View.Cast<object>().All(i => IsItemSelectedByValue(PropertyAccess.GetValue(i, ValueProperty)));
            }

            return View != null && selectedItems.Count == count;
            //return View != null && selectedItems.Count == View.Cast<object>().Count();
        }

Of course, it is not easy to implement a select all logic for a virtualized list.

My fix is not perfect but feels better.
Can you do something with my approach?

-tom

I’m afraid that this code doesn’t make sense. default(int) is always 0 and Count works only when LoadData is used. Not sure about the preprocessor at all.

@enchev

Exactly I use LoadData method.
I could not use the count directly so I created an intermediate variable.

Count

And yes you are right if the condition is not true count remains 0.
I just wanted to test if the behavior is correct.

-tom

@enchev

I wanted to show you what kind of behavior I would expect with the SelectAllCheckBox.
It would be wonderful if you could fix the logic of the SelectAllCheckBox?

But I also understand if this has no priority at the moment.

-tom

Hi,
Is there anything new here?
Is this still being fixed?

-tom