【问题标题】:WPF combo box not binding on changeWPF 组合框对更改没有约束力
【发布时间】:2015-04-07 14:47:04
【问题描述】:

我有 3 个组合框

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

组合框的列表是 { a,b,c,d} 因此,如果在第一个框中选择了“b”,则下拉菜单不应包含 b,如果第二个设置为 a,则需要使用 {a,c,d} 进行更新,那么最后一个需要具有 {c, d}。如果他们返回并更改任何内容,我们需要相应地更新列表。我添加了一个事件 oncomboboxchanged 但它没有更新组合框,当我将项目源设置为新列表时。

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);
          }
       }
   }
}

所以 cbo.ItemSource 没有做任何事情,我是否需要做任何不同的事情才能看到更新。

【问题讨论】:

  • 什么是 comboList ?您首先在哪里提供 itemssource?
  • 我用添加到项目源的代码编辑了帖子
  • 如果你从第一秒选择 a 将有 BCD,如果你在第二秒选择 b A 仍然有 ABCD?
  • 所有项目都不应重复

标签: c# .net wpf combobox


【解决方案1】:
  1. 您需要在 XAML 中使用绑定,而不是在后面的代码中设置 ItemsSource。还有数据绑定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. 在你后面的代码中,你需要实现INotifyPropertyChanged;将您的相关 ItemsSources 和 SlectedItems 定义为属性;并将您的 Windows 的 DataContext 设置为您的代码本身(您应该使用 MVVM 模式,但稍后您可能会担心):

    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));
        }
    }
    

结果:

三个组合框在初始阶段都会显示A,B,C,D。和 那么如果用户选择 cbo2cbo3 将只显示 动态过滤结果。

我意识到这不是你想要的 100%(感谢@TheodosiusVonRichhofen),但我觉得你仍然可以使用它,并且能够轻松修改它以满足你的需求。

【讨论】:

  • 非常感谢您的帮助,我尝试用我的代码实现这一点,但它加载了空的下拉框。
  • @user565992,你有没有在MainWindow的构造MainWindow()中添加this.DataContext=this;
  • 再次感谢您!它加载项目。我是否需要添加 oncombobox 更改事件。因为组合框仍然显示所有值
  • ...所以如果你为第二个组合选择“B”,第一个组合仍然有“B”作为选择,因为它的 itemsource 从未被过滤?这是OP想要的吗?
  • @TheodosiusVonRichthofen,好地方,非常感谢!根据 OP 的评论,看起来 OP 不想重复,(我认为它对用户不太友好)但我承认我错过了这一点,尽管使用这种方法可以轻松修改它。
【解决方案2】:

此外,包含组合框项目的列表应该是 ObservableCollection 而不是列表。通过将其设为 ObservableCollection,组合框项目将在您添加/删除/更改列表中的项目时更新。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多