user565992
user565992

Reputation: 497

WPF combo box not binding on change

I have 3 combo boxes

<Grid>
   <ComboBox Name="cbo1" SelectionChanged="OnComboBoxChanged" />
   <ComboBox Name="cbo2" SelectionChanged="OnComboBoxChanged"/>
   <ComboBox Name="cbo3" SelectionChanged="OnComboBoxChanged" />

The list for combo boxes is { a,b,c,d} so if "b" is selected in the first box then the drop down should not have b and it will need to updated with {a,c,d} if the second one is set to a then last one need to have {c,d}. if they go back and change any we need to update the list accordingly. I addded a event oncomboboxchanged but it is not updating the combo box , when i set the item source to the new list.

private List<string> comboList = new List<string>();
string[] defaultParam = { "A", "B", "C", "D" };

public MainWindow()
{   
       InitializeComponent();
       foreach(string s in defaultParam)
       {
           LoadCombo(s);
       } 

}
public void LoadCombo(string name)
{
   comboList.Add(name); 
   cbo1.ItemsSource = comboList;
   cbo2.ItemsSource = comboList;
   cbo3.ItemsSource = comboList;
}
private void OnComboBoxChanged(object sender,SelectionChangedEventArgs e)
{
   var combo = sender as ComboBox;
   string oldval = combo.Text;
   string id = combo.Name;
   string itemSel = (sender as ComboBox).SelectedItem.ToString();
   comboList.Remove(itemSel);
   //add old value only if it is not empty
   if (!string.IsNullOrEmpty(oldval))
   {
      comboList.Add(oldval);
   }
   combo.ItemsSource = comboList;
   ComboBox[] comboNameLst = {cbo1,cbo2,cbo3 }; 
   foreach (ComboBox cbo in comboNameLst)
   {
       if (id != cbo.Name)
       {
          if (cbo.SelectedItem == null)
          {
              cbo.ItemsSource = comboList;
          }
          else if (cbo.SelectedItem != null)
          {
             string tempitemsel = cbo.SelectedItem.ToString();
             comboList.Add(tempitemsel);
             cbo.ItemsSource = comboList;
             comboList.Remove(tempitemsel);
          }
       }
   }
}

so cbo.ItemSource is not doing any thing , do I need to do any thing differently so I see the update.

Upvotes: 1

Views: 794

Answers (2)

Bolu
Bolu

Reputation: 8786

  1. You need to use binding in XAML, rather than set ItemsSource in your code behind. Also data bind SelectedItem:

     <Grid>
         <ComboBox ItemsSource="{Binding DefaultList}" SelectedItem="{Binding SelectedItem_Cob1}"/>
         <ComboBox ItemsSource="{Binding FilteredListA}" SelectedItem="{Binding SelectedItem_Cob2}"/>
         <ComboBox ItemsSource="{Binding FilteredListB}" SelectedItem="{Binding SelectedItem_Cob3}"/>
     </Grid>
    
  2. In your code behind, you need to implement INotifyPropertyChanged; define your relevant ItemsSources, and SlectedItems as properties; and set your Windows's DataContext to your code itself (you should use MVVM pattern but you could worry about that later) :

    using System.ComponentModel;
    public partial class MainWindow: INotifyPropertyChanged
    { 
        string[] defaultParam = { "A", "B", "C", "D" };
        private string _selecteditem_cob1;
        private string _selecteditem_cob2;
        private string _selecteditem_cob3;
    
        public List<string> DefaultList
        {
            get { return defaultParam.ToList(); }
        }
    
        public string SelectedItem_Cob1
        {
            get { return _selecteditem_cob1; }
            set
            {
                if (_selecteditem_cob1 != value)
                {
                    _selecteditem_cob1 = value;
                    RaisePropertyChanged("SelectedItem_Cob1");
                    RaisePropertyChanged("FilteredListA");
                    RaisePropertyChanged("FilteredListB");
                }
            }
        }
    
        public string SelectedItem_Cob2
        {
            get { return _selecteditem_cob2; }
            set
            {
                if (_selecteditem_cob2 != value)
                {
                    _selecteditem_cob2 = value;
                    RaisePropertyChanged("SelectedItem_Cob2");
                    RaisePropertyChanged("FilteredListB");
                }
            }
        }
    
        public string SelectedItem_Cob3
        {
            get { return _selecteditem_cob3; }
            set
            {
                if (_selecteditem_cob3 != value)
                {
                    _selecteditem_cob3 = value;
                    RaisePropertyChanged("SelectedItem_Cob3");
                }
            }
        }
    
        public List<string> FilteredListA
        {
            get { return defaultParam.ToList().Where(a=>a!=SelectedItem_Cob1).ToList(); }
        }
        public List<string> FilteredListB
        {
            get { return FilteredListA.Where(a => a != SelectedItem_Cob2).ToList(); }
        }
        public MainWindow()
        {
    
            InitializeComponent();  
            this.DataContext=this;          
        }
    
        //Implementation for INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            var handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, e);
            }
        }
    
        protected void RaisePropertyChanged(String propertyName)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
    }
    

Result:

Three ComboBoxes will all show A,B,C,D at the initial stage. And then if user made selections cbo2 and cbo3 will only display filtered result dynamically.

I realized this is not 100% what you want (thanks to @TheodosiusVonRichthofen), but I feel you can still use this, and be able to easily modify it to suit your needs.

Upvotes: 3

mdebeus
mdebeus

Reputation: 1928

Also, the list that contains the combo-box items should be an ObservableCollection instead of a List. By making it an ObservableCollection, the combo-box items will be updated when you add/remove/change items in the lists.

Upvotes: 1

Related Questions