Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Combobox with same Itemsource but the SelectedItem should be different - WPF

Goal is to have multiple Combobox, once the item is selected in any of the Combobox, it should be removed or hided from other Comboboxes for selection.

I'm able to change the source whenever the selection got changed on any of the Comboboxes. But Problem is when I remove the selected item from the ItemsSource, item got removed from all the sources including the one on which I selected.

Here is the sample

xaml

<StackPanel>
    <ComboBox Width="100" Height="50" SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding ComboboxItems}" />
    <ComboBox Width="100" Height="50" SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding ComboboxItems}" />
    <ComboBox Width="100" Height="50" SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding ComboboxItems}" />
    <ComboBox Width="100" Height="50" SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding ComboboxItems}" />
</StackPanel>

Codebehind

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        ObservableCollection<string> s = new ObservableCollection<string>();
        s.Add("item1");
        s.Add("item2");
        s.Add("item3");
        s.Add("item4");
        s.Add("item5");
        s.Add("item6");

        DataContext = new MainViewModel() { ComboboxItems = s , SelectedItem = "item2" };

    }
}

public class MainViewModel : INotifyPropertyChanged
{
    private ObservableCollection<string> comboboxitems;

    public ObservableCollection<string> ComboboxItems
    {
        get { return comboboxitems; }  
        set { comboboxitems = value; OnPropertyChanged("ComboboxItem"); }
    }

    private string _selectedItem;

    public string SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            _selectedItem = value;
            comboboxitems.Remove(value);  //here removing selected item from itemssource
            OnPropertyChanged("SelectedItem");
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propname)
    {
        if(PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propname));
    }
}

I know I can have multiple Collection for each Combobox but that may take lot of memory if number of Combobox increases.

Hope, there should be a easy way to achieve this in WPF.

like image 559
Gopichandar Avatar asked May 18 '16 10:05

Gopichandar


1 Answers

You could define different SelectedItem for each ComboBox, and then create a wrapper of the SharedItemSource for each ComboBoxto filter out the SelectedItem of other ComboBox. eg:

C# :

    public IEnumerable<string> ComboboxItems1
    {
        get
        {
            return ComboboxItems.Where(x => x != SelectedItem2 && x != SelectedItem3);
        }
    }

    public string SelectedItem1
    {
        get { return _selectedItem1; }
        set
        {
            if (_selectedItem1 != value)
            {
                _selectedItem1 = value;
                RaisePropertyChanged("SelectedItem1");
                RaisePropertyChanged("ComboboxItems2"); //raise propertychanged to refresh GUI 
                RaisePropertyChanged("ComboboxItems3");
            }
        }
    }       

    public IEnumerable<string> ComboboxItems2
    {
        get
        {
            return ComboboxItems.Where(x => x!=SelectedItem1&&x!=SelectedItem3);
        }
    }

    public string SelectedItem2
    {
        get { return _selectedItem2; }
        set
        {
            if (_selectedItem2 != value)
            {
                _selectedItem2 = value;                   
                RaisePropertyChanged("SelectedItem2");
                RaisePropertyChanged("ComboboxItems1"); //raise propertychanged to refresh GUI
                RaisePropertyChanged("ComboboxItems3");
            }
        }
    }

    public IEnumerable<string> ComboboxItems3
    {
        get
        {
            return ComboboxItems.Where(x => x != SelectedItem1 && x != SelectedItem2);
        }
    }

    public string SelectedItem3
    {
        get { return _selectedItem3; }
        set
        {
            if (_selectedItem3 != value)
            {
                _selectedItem3 = value;                 
                RaisePropertyChanged("SelectedItem3");
                RaisePropertyChanged("ComboboxItems1"); //raise propertychanged to refresh GUI
                RaisePropertyChanged("ComboboxItems2");
            }
        }
    }

XAML:

<ComboBox SelectedItem="{Binding SelectedItem1}" ItemsSource="{Binding ComboboxItems1}" />
<ComboBox  SelectedItem="{Binding SelectedItem2}" ItemsSource="{Binding ComboboxItems2}" />
<ComboBox  SelectedItem="{Binding SelectedItem3}" ItemsSource="{Binding ComboboxItems3}" />
like image 66
Bolu Avatar answered Oct 31 '22 16:10

Bolu