当另一个组合框选择项改变时更改组合框项目?

时间:2017-08-25 04:05:18

标签: c# wpf data-binding combobox

我在视图中有两个ComboBox。我想在第一个选定项目更改时更改第二个项目源:

视图:

<ComboBox ItemsSource="{Binding ProductsList}" SelectedValue="{Binding SelectedProduct}" DisplayMemberPath="ChipName"/>

ViewModel:

    public MainViewModel()
    {
        GetProductsList();
    }

    ProductDb pd = new ProductDb();
    public ObservableCollection<Product> ProductsList { get; set; }
    private void GetProductsList()
    {
        try
        {
            ProductsList = new ObservableCollection<Product>(pd.GetProducts());
        }
        catch(Exception e) { Console.WriteLine(e.ToString()); }
        if (ProductsList != null) SelectedProduct = ProductsList[0];
    }

模型从xml中读取数据:

public class ProductDb
{
    public ObservableCollection<Product> GetProducts()
    {
        ObservableCollection<Product> _products = new ObservableCollection<Product>();
        XDocument doc = XDocument.Load(@".\Config\Chip.xml");
        foreach(XElement productRow in doc.Root.Elements("Chip"))
        {
            var p = new Product(productRow.Element("ChipName").Value, productRow.Element("Series").Value, productRow.Element("Type").Value,
                Convert.ToUInt32(productRow.Element("FlashAddress").Value), Convert.ToUInt32(productRow.Element("PageCount").Value), Convert.ToUInt32(productRow.Element("PageSize").Value),
                Convert.ToUInt32(productRow.Element("RAMAdd").Value, 16), Convert.ToUInt32(productRow.Element("RAMLength").Value, 16), productRow.Element("Crystals").Value);

            foreach (XElement crystal in productRow.Element("Crystals").Elements())
            {
                p.Crystals.Add(crystal.Value);
            }
            _products.Add(p);
        }
        return _products;
    }
}

现在上面的代码填充了第一个组合框中的ChipName,我想在sencond组合框中显示Craystal的{​​{1}}。我应该怎么做?提前谢谢!

---的更新 ---

晶体是产品的一个元素。它包含几个水晶。 xml文件如下所示:

SelectedProdu

4 个答案:

答案 0 :(得分:1)

就像你已经为产品做的那样,但需要告诉UI在哪里找到新组合的新项目来源:

XAML:

  <ComboBox ItemsSource="{Binding Crystals}" 
            SelectedValue="{Binding SelectedCrystal}" 
            DisplayMemberPath="CrystalName"/>

C#:

public Product SelectedProduct
{
  set 
    {
       // your private member setting...
       // raise property change for crystal collection for UI to respond
    }
}

public Product SelectedCrystal
{
  set 
  {
     // your private member setting...
     // raise property change for crystal collection for UI to respond
  }
}

public ObservableCollection<Crystal> Crystals
{
  get 
    {
       if (SelectedProduct != null)
         return SelectedProduct.Crystals;

       return new ObservableCollection<Crystal>();
    }
}

如果您愿意,您还可以根据其绑定集合中是否有任何有效对象来使用水晶控件的可见性或启用状态...

答案 1 :(得分:1)

如果你实现INotifyPropertyChanged接口并为PropertyChanged属性引发SelectedProduct事件,这应该可以工作:

<ComboBox ItemsSource="{Binding SelectedProduct.Crystals}" />

如果CrystalsProduct类的公共属性,这也应该有效:

<ComboBox x:Name="a" ItemsSource="{Binding ProductsList}"
                  SelectedValue="{Binding SelectedProduct}"
                  DisplayMemberPath="ChipName"/>

<ComboBox x:Name="b" ItemsSource="{Binding SelectedItem.Crystals, ElementName=a}" />

答案 2 :(得分:0)

XAML:

<ComboBox ItemsSource="{Binding ProductsList}" SelectedItem="{Binding SelectedProduct,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="ChipName"/>
<ComboBox ItemsSource="{Binding Crystals}" />

C#:

public class MainModel:INotifyPropertyChanged    
{   
        event PropertyChangedEventHandler PropertyChanged;  
        ObservableCollection<Product> _ProductsList = null;  
        ObservableCollection<Crystal> Crystals = null;  
        Product _SelectedProduct = null;

    public ObservableCollection<Product> ProductsList   
    {
        get
        {
            return _ProductsList;
        } 
        set
        {
            _ProductsList=value;
            PropertyChanged?.Invoke(this,new System.ComponentModel.PropertyChangedEventArgs("ProductsList")); 
        }
    }  

    public ObservableCollection<Crystal> Crystals    
    {
        get
        {
            return _Crystals;
        } 
        set
        {
            _Crystals=value;
            PropertyChanged?.Invoke(this,new System.ComponentModel.PropertyChangedEventArgs("Crystals")); 
        }
    } 

    public Product SelectedProduct
    {
        get
        {
            return _SelectedProduct;
        }
        set
        {
            _SelectedProduct = value;
            PropertyChanged?.Invoke(this,new System.ComponentModel.PropertyChangedEventArgs("SelectedProduct")); 
            ResetCrystals();
        }
    } 
    private void ResetCrystals()
    {
         Crystals=.....
    }
}

答案 3 :(得分:0)

你尝试过这样的事情吗?

<StackPanel>
        <ComboBox Width="100" Height="22" ItemsSource="{Binding ProductsList}" SelectedValue="{Binding SelectedProduct}" DisplayMemberPath="ChipName"/>
        <ComboBox Width="100" Height="22" ItemsSource="{Binding SelectedProduct.Crystals}"  DisplayMemberPath="Value"/>    
</StackPanel>

对我来说,这很有效,我只是将Product.Crystals设置为ObservableCollection,并SelectedProduct使用INotifyPropertyChanged接口

例如: 查看型号:

        public ObservableCollection<Product> ProductsList { set; get; }
        public Product SelectedProduct
        {
            set
            {
                _selectedProduct = value;
                NotifyPropertyChanged();
            }
            get
            {
                return _selectedProduct;
            }
        }

型号:

public class Product
    {
        public ObservableCollection<Crystal> Crystals { set; get; }
        public String ChipName { set; get; }
        public Product(ObservableCollection<Crystal> l, String ChipName)
        {
            this.ChipName = ChipName;
            Crystals = l;
        }
    }

    public class Crystal
    {
        public string Value { set; get; }
    }