xceedsoftware / wpftoolkit

All the controls missing in WPF. Over 1 million downloads.
Other
3.87k stars 873 forks source link

CheckComboBox.SelectedItemsOverride Loses All Selections #1589

Open MaroisConsulting opened 4 years ago

MaroisConsulting commented 4 years ago

I have a CheckComboBox on a tab control. I populate the ItemsSource and SelectedItemsOverride and everything seems to work fine. Both lists are ObservableCollections.

If I navigate to another tab, as soon as the current tab loses foces the control removes each item from the SelectedItemsOverride list. The CollectionChanges event for the SelectedItemsOverride list is called once for each item as it's being removed.

There is no other code getting called in my View & ViewModel that I can see. There's nothing in the call stack exept "External Code"

XceedBoucherS commented 4 years ago

Hi, I cannot reproduce this issue in v3.8 and up. Here's the sample I used:

  <TabItem Header="Second">
    <TextBox Text="ABC" />
  </TabItem>
</TabControl>

`public partial class MainWindow : Window { public MainWindow() { InitializeComponent();

  this.DataContext = this;

  this.Players = new ObservableCollection<Player>()
  {
    new Player() { FirstName = "Carey", LastName = "Price" },
    new Player() { FirstName = "Max", LastName = "Domi" },
    new Player() { FirstName = "Shea", LastName = "Weber" },
    new Player() { FirstName = "Jonathan", LastName = "Drouin" },
    new Player() { FirstName = "Brendan", LastName = "Gallagher" },
  };

  this.SelectedPlayers = new ObservableCollection<Player>();
  this.SelectedPlayers.CollectionChanged += SelectedPlayers_CollectionChanged;
}

private void SelectedPlayers_CollectionChanged( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e )
{
}

public ObservableCollection<Player> Players
{
  get;
  set;
}

public ObservableCollection<Player> SelectedPlayers
{
  get;
  set;
}

}

public class Player { public string FirstName { get; set; } public string LastName { get; set; } }`

Leszy77 commented 4 years ago

When "SelectedPlayers" collection is a ReactiveUI.ReactiveList, it works ok in version 3.2.0. The bug exists in version 3.5.0 and the latest, 4.0.1.

I have no idea why this happens. Any clues would be appreciated.

Alex-ok2005 commented 4 years ago

I have the same problem. Is there any solution?

If you switch TabControl several times, CheckComboBox loses its selection. But not completely. In accordance with the smallest number of items used in other CheckComboBox items.

ViewModel:

    public class ViewModel : INotifyPropertyChanged
    {
        private Client selectedClient;
        public Client SelectedClient
        {
            get { return selectedClient; }
            set
            {
                selectedClient = value;
                OnPropertyChanged("SelectedClient");
            }
        }
        public class Client : INotifyPropertyChanged
        {
            private string clientName;
            public string ClientName
            {
                get { return clientName; }
                set
                {
                    clientName = value;
                    OnPropertyChanged("ClientName");
                }
            }
            public ObservableCollection<string> OrderItems { get; set; }
            public ObservableCollection<string> SelectedOrderItems { get; set; }
            public Client(string newClient)
            {
                ClientName = newClient;
                OrderItems = new ObservableCollection<string>();
                SelectedOrderItems = new ObservableCollection<string>();
            }
            public event PropertyChangedEventHandler PropertyChanged;
            public void OnPropertyChanged([CallerMemberName]string prop = "")
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
            }
        }
        public ObservableCollection<Client> Clients { get; set; }
        public ViewModel()
        {
            Clients = new ObservableCollection<Client>();
            Client _client = new Client("Client No.1");
            _client.OrderItems.Add("Order No.1");
            _client.SelectedOrderItems.Add("Order No.1");
            Clients.Add(_client);

            _client = new Client("Client No.2");
            _client.OrderItems.Add("Order No.1");
            _client.OrderItems.Add("Order No.2");
            _client.SelectedOrderItems.Add("Order No.1");
            _client.SelectedOrderItems.Add("Order No.2");
            Clients.Add(_client);

            _client = new Client("Client No.3");
            _client.OrderItems.Add("Order No.1");
            _client.OrderItems.Add("Order No.2");
            _client.OrderItems.Add("Order No.3");
            _client.SelectedOrderItems.Add("Order No.1");
            _client.SelectedOrderItems.Add("Order No.2");
            _client.SelectedOrderItems.Add("Order No.3");
            Clients.Add(_client);

            SelectedClient = Clients.FirstOrDefault();
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged([CallerMemberName]string prop = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
        }
    }

XAML:

<Window x:Class="TestCheckComboBox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestCheckComboBox"
        xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="400" WindowStartupLocation="CenterScreen">
    <Grid>
        <TabControl
            ItemsSource="{Binding Clients}"
            SelectedItem="{Binding SelectedClient, Mode=TwoWay}" Margin="10">
            <TabControl.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding ClientName}" />
                </DataTemplate>
            </TabControl.ItemTemplate>
            <TabControl.ContentTemplate>
                <DataTemplate>
                    <Grid>
                        <xctk:CheckComboBox 
                            VerticalAlignment="Top"
                            Height="25"
                            Width="200"
                            Margin="20,20,0,0"
                            ItemsSource="{Binding OrderItems, Mode=OneWay}"
                            Delimiter = "; "
                            SelectedItemsOverride="{Binding SelectedOrderItems, Mode=TwoWay}">
                        </xctk:CheckComboBox>
                    </Grid>
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>
    </Grid>
</Window>

Full project code

XceedBoucherS commented 4 years ago

Hi, I was able to reproduce @Alex-ok2005 issue. This will be fixed in v4.1. In the meantime, go in file Xceed.Wpf.Toolkit/Primitives/Selector.cs: 1) In method OnItemsSourceChanged, add the check: if( this.SelectedItemsOverride == null ) just before calling this.RemoveUnavailableSelectedItems();

2) In method OnItemsChanged, add the check: if( this.ItemsSource == null ) justr before calling this.RemoveUnavailableSelectedItems();

Alex-ok2005 commented 4 years ago

Thank's a lot, it worked