将一个ComboBox的DataSource绑定到另一个

时间:2018-03-07 13:33:51

标签: c# winforms data-binding

我有两个组合框envelopeListdatasetList。请考虑以下代码行:

envelopeList.DataBindings.Add("DataSource", datasetList, "SelectedValue");

预期的功能是在更改选择时将envelopeList.DataSource更新为datasetList.SelectedValue。但是,如果datasetList为空,则抛出ArgumentException说“附加信息:复杂数据绑定接受IList或IListSource作为数据源。”

我不明白为什么会这样。当datasetList为空时datasetList.SelectedValue返回null,envelopeList.DataSource = null不会抛出任何异常。这不会引发任何例外:envelopeList.DataSource = datasetList.SelectedValue;,也不会:envelopeList.DataSource = new BindingSource(datasetList, "SelectedValue");,即使datasetList为空。

datasetList之后执行绑定至少有一个项目按预期工作,直到它变为空,在这种情况下envelopeList.DataSource不会更新。 DataSourceChanged事件甚至没有被触发。 (虽然在我的情况下,用户注意到,因为删除datasetList中的项目时数据源将被清空)。

为了完成这项工作,我必须在第一次填充datasetList后执行以下代码:

if(doonce && !(doonce = false))
    envelopeList.DataBindings.Add("DataSource", datasetList, "SelectedValue");

这是一种非常难看的方式,我宁愿在初始化期间能够做到这一点。

一些可能重要的信息。

两个ComboBox实际上都是我自己的继承类型AdvancedComboBox。这是以下内容中的相关功能:

public class AdvancedComboBox : ComboBox, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected override void OnSelectedValueChanged(EventArgs e)
    {
        base.OnSelectedValueChanged(e);
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedValue")); //I don't know why, but it works even if I remove this line.
    }
}

(我对PropertyChanged事件有其他用途,即使我显然不需要SelectedValue属性。)

datasetList.DataSource绑定到包含IBindingListDatasetPresenter个对象的DatasetPresenter Areas有一个属性IBindingList,可返回envelopeList,其中包含我想要datasetList.ValueMember = "Areas"显示的对象。
我在进行绑定之前运行envelopeList.DataBindings.Add("DataSource", datasetList, "SelectedValue");

问题

即使datasetList为空或取得类似结果,如何使AdvancedComboBox正常工作?
我更喜欢在ComboBox的初始化期间执行的解决方案和/或我可以放在datasetList类中的代码,以便它保持自包含。

奖励:为什么datasetList.SelectedValue为空时不起作用?即使envelopeList.DataSource = null返回null并且<!DOCTYPE html> <html> <head> <style> .box { width: 10vw; height: 10vw; background-color: yellow; border: solid black; display: block } .cont { position: relative; display: block; } .cont>.box { position: absolute; display: block; } </style> </head> <body> <div class="box">1</div> <div class="cont"> <div class="box">2</div> </div> <div class="box">3</div> </body> </html>也没问题。

1 个答案:

答案 0 :(得分:0)

嗯,我找到了一个解决方案,但它并不漂亮。

我专门为此目的创建了这个类:

private class PlaceHolder
{
    public string Name { get; }//This property is the DisplayMember of both ComboBoxes.
    public List<PlaceHolder> Areas { get { return new List<PlaceHolder>(0); } }//This property is the ValueMember of datasetList.
}

在初始化期间,我运行此代码。

datasetList.DataSource = new List<PlaceHolder>() { new PlaceHolder() };
envelopeList.DataBindings.Add("DataSource", datasetList, "SelectedValue");
datasetList.DataSource = myController.Datasets;//This is the intended data source.

这很难看,我仍然在寻找更好的解决方案。