RadzenDropDown: desynchronization between Select/unselect, ClearAll and empty Data-binding

Hi guys!

using RadzenDropDown with multiple=true.

If you select all the items with the "select/unselect all ckeckbox", then clear all selected Items with Clear Icon and then try again to select all with "select/unselect all ckeckbox" you new to click twice on the checkbox to select all items again.

This also happens if instead of clear all the selected items with the clear icon you set the bind-Value to Enumerable.Empty().

In my opinion and if it helps, it seems like there is some boolean toggle variable that is only updated with the "select/unselect all ckeckbox", so that function does not verify that the list of selected items is empty before to choose between select or unselect all.

TIA!

p.d. Radzen.Blazor Version 1.1.21

Just published Radzen.Blazor 1.1.22 with fix included.

@enchev, I have tested yout last change for Dropbox and Clear Icon is working ok!, Thank you so much!

But there is some little bugs yet, as a example speaks a thousand words, I've attached a example to help you to debug them.

a) Choose one or more Customer and then In order Dropbox select someone or all (There is not posible to check any)
b) After you resolve this, Please, make the same, Choose one or more Customer and then In order Dropbox select all, and then again, Choose one or more other Customer (Every time you change customer selection, OrderIDs is Empty set) and finally try to select all in Order Dropbox, You will need on Order Dropbox select all checkbox click twice.

====== CODE ========== 
@page "/cascading-dropdowns-test"

@using NorthwindBlazor.Data
@using NorthwindBlazor.Models.Northwind
@using Microsoft.EntityFrameworkCore

@inject NorthwindContext dbContext

<p>This page demonstrates cascading <b>DropDown</b> component.</p>
<RadzenCard>
    <div class="row">
        <div class="col-md-6">
            <h3>Customers</h3>
            <RadzenDropDown Multiple="true" AllowClear="true" Change="SelectCustomer" @bind-Value="CustomerIDs" Placeholder="Select customer" AllowFiltering="true" Data="@(customers)" TextProperty="CompanyName" ValueProperty="CustomerID" Style="margin-bottom: 20px" />
        </div>
        <div class="col-md-6">
            <h3>Orders</h3>
            <RadzenDropDown Multiple="true" AllowClear="true" Disabled="@(orders.Where(o => CustomerIDs?.Contains(o.CustomerID) ?? false).Count() == 0)" TValue="IEnumerable<int>" @bind-Value="OrderIDs" Placeholder="Select order" Data="@(orders.Where(o => CustomerIDs?.Contains(o.CustomerID) ?? false))" TextProperty="OrderDate" ValueProperty="OrderID" Style="margin-bottom: 20px">
                <Template>
                    Order Date: @String.Format("{0:d}", ((Order)context).OrderDate)
                </Template>
            </RadzenDropDown>
        </div>
    </div>
    <div class="row">
        <div class="col-md-12">
            <h3>Order Details</h3>
            <RadzenGrid AllowFiltering="true" AllowPaging="true" AllowSorting="true" FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive"
                        Data="@(orderDetails.Where(o => OrderIDs?.Contains(o.OrderID) ?? false))" TItem="OrderDetail" ColumnWidth="200px">
                <Columns>
                    <RadzenGridColumn TItem="OrderDetail" Property="Product.ProductName" Title="Product" />
                    <RadzenGridColumn TItem="OrderDetail" Property="Quantity" Title="Quantity" />
                    <RadzenGridColumn TItem="OrderDetail" Property="Discount" Title="Discount" FormatString="{0:P}" />
                </Columns>
            </RadzenGrid>
        </div>
    </div>
</RadzenCard>

@code {
    IEnumerable<Customer> customers;
    IEnumerable<Order> orders;
    IEnumerable<OrderDetail> orderDetails;


    IEnumerable<string> CustomerIDs = Enumerable.Empty<string>();
    IEnumerable<int> OrderIDs = Enumerable.Empty<int>();

    protected void SelectCustomer(object value)
    {
        OrderIDs = Enumerable.Empty<int>();
    }

    protected override async Task OnInitializedAsync()
    {
        customers = await Task.FromResult(dbContext.Customers.ToList());
        orders = await Task.FromResult(dbContext.Orders);
        orderDetails = await Task.FromResult(dbContext.OrderDetails.Include("Product"));
    }
}

Hi @ctnet,

This way is not going to work since using such expression Data="@(orders.Where(o => CustomerIDs?.Contains(o.CustomerID) ?? false))" you are forcing Blazor to set the Data property on each state change, which will clear the entire state of the component including selected items. Here is how to make this work:

<RadzenCard>
    <div class="row">
        <div class="col-md-6">
            <h3>Customers</h3>
            <RadzenDropDown @bind-Value="CustomerIDs" Data="@customers" 
                            Multiple="true" AllowClear="true" Placeholder="Select customer" AllowFiltering="true" 
                            TextProperty="CompanyName" ValueProperty="CustomerID" Style="margin-bottom: 20px" />
        </div>
        <div class="col-md-6">
            <h3>Orders</h3>
            <RadzenDropDown @bind-Value="OrderIDs" Data="@orders"  
                            Multiple="true" AllowClear="true" Placeholder="Select order" 
                            TextProperty="OrderDate" ValueProperty="OrderID" Style="margin-bottom: 20px">
                <Template>
                    Order Date: @String.Format("{0:d}", ((Order)context).OrderDate)
                </Template>
            </RadzenDropDown>
        </div>
    </div>
    <div class="row">
        <div class="col-md-12">
            <h3>Order Details</h3>
            <RadzenGrid AllowFiltering="true" AllowPaging="true" AllowSorting="true" FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive"
                        Data="@orderDetails" TItem="OrderDetail" ColumnWidth="200px">
                <Columns>
                    <RadzenGridColumn TItem="OrderDetail" Property="Product.ProductName" Title="Product" />
                    <RadzenGridColumn TItem="OrderDetail" Property="Quantity" Title="Quantity" />
                    <RadzenGridColumn TItem="OrderDetail" Property="Discount" Title="Discount" FormatString="{0:P}" />
                </Columns>
            </RadzenGrid>
        </div>
    </div>
</RadzenCard>

@code {
    IEnumerable<Customer> customers;
    IEnumerable<Order> orders;
    IEnumerable<OrderDetail> orderDetails;


    IEnumerable<string> customerIDs = Enumerable.Empty<string>();
    IEnumerable<string> CustomerIDs
    {
        get
        {
            return customerIDs;
        }
        set
        {
            if (customerIDs != value)
            {
                customerIDs = value;
                GetOrders();
            }
        }
    }

    IEnumerable<int> orderIDs = Enumerable.Empty<int>();
    IEnumerable<int> OrderIDs
    {
        get
        {
            return orderIDs;
        }
        set
        {
            if (orderIDs != value)
            {
                orderIDs = value;
                GetOrderDetails();
            }
        }
    }

    async void GetOrders()
    { 
        orders = await Task.FromResult(dbContext.Orders.Where(o => CustomerIDs.ToList().Contains(o.CustomerID)).ToList());
    }

    async void GetOrderDetails()
    { 
        orderDetails = await Task.FromResult(dbContext.OrderDetails.Where(o => OrderIDs.ToList().Contains(o.OrderID)).Include("Product").ToList());
    }

    protected override async Task OnInitializedAsync()
    {
        customers = await Task.FromResult(dbContext.Customers.ToList());
        GetOrders();
        GetOrderDetails();
    }
}

@enchev Your code works like a charm! Thank you a lot!

Everyting is working ok but "select/unselect all ckeckbox" in one case.
Please, with your code could yout do next:
"Choose one or more Customer and then in orders Dropdown select all items with "select/unselect all ckeckbox", that's work ok!, after that Choose one or more other Customer and finally try to select all in Orders Dropdown, You will need on Order Dropbox select all checkbox click twice"

I've attached a video in order to help

SelectAllVideo.zip (261.2 KB)

Hi @enchev,
A posible solution could be, in "select/unselect all ckeckbox function", to check @bind-Value variable : "bind-Value".Count() == 0 ? "Select all" : "bind-Value".Count() == "Data".Count() ? "unselect all" : "Select all". Or perhaps make some method "select all, unselect all, clear all" public or protected?, because using binding it's no working in all case inside Dropdown code