具有相同数据源的多个组合框 (C#)
Posted
技术标签:
【中文标题】具有相同数据源的多个组合框 (C#)【英文标题】:Multiple Combo Boxes With The Same Data Source (C#) 【发布时间】:2011-05-19 15:57:54 【问题描述】:更新:现已解决,请参阅下面的答案。
在我的一个表单上(在 Windows 表单应用程序中)我有 3 个组合框。这些组合框需要显示价格列表(在文本中,具有整数后端值)。
所有这些组合框都使用相同的数据源(TSPrice 类型的 List,ValueMember 设置为 Price,DisplayMember 设置为 Description)。
我的问题是...每次我从下拉列表中选择一个价格选项时,它们都会更改为相同的值...这与它们都绑定到同一个数据源有关吗?
我是这样绑定它们的:
var priceList = new List<TSPrice>
new TSPrice(0, ""),
new TSPrice(0, "Half Day"),
new TSPrice(0, "Full Day"),
new TSPrice(0, "1 + Half"),
new TSPrice(0, "2 Days"),
new TSPrice(0, "Formal Quote Required")
;
objInsuredPrice.DataSource = priceList;
objTPPrice.DataSource = priceList;
objProvSum.DataSource = priceList;
objInsuredPrice.ValueMember = "Price";
objTPPrice.ValueMember = "Price";
objProvSum.ValueMember = "Price";
objInsuredPrice.DisplayMember = "Description";
objTPPrice.DisplayMember = "Description";
objProvSum.DisplayMember = "Description";
objInsuredPrice.SelectedIndex = 0;
objTPPrice.SelectedIndex = 0;
objProvSum.SelectedIndex = 0;
//objInsuredPrice.DataSource = objTPPrice.DataSource = objProvSum.DataSource = priceList;
//objInsuredPrice.ValueMember = objTPPrice.ValueMember = objProvSum.ValueMember = "Price";
//objInsuredPrice.DisplayMember = objTPPrice.DisplayMember = objProvSum.DisplayMember = "Description";
//objInsuredPrice.SelectedIndex = objTPPrice.SelectedIndex = objProvSum.SelectedIndex = 0;
编辑:问题是它们都被绑定到同一个数据源,正如 Saurabh 所确认的那样。我就是这样解决的。
var priceList = new List<TSPrice>
new TSPrice(0, ""),
new TSPrice(1, "Half Day"),
new TSPrice(2, "Full Day"),
new TSPrice(3, "1 + Half"),
new TSPrice(4, "2 Days"),
new TSPrice(5, "Formal Quote Required")
;
var insuredList = new TSPrice[5];
var TPList = new TSPrice[5];
var provList = new TSPrice[5];
priceList.CopyTo(insuredList);
priceList.CopyTo(TPList);
priceList.CopyTo(provList);
objInsuredPrice.DataSource = insuredList;
objTPPrice.DataSource = TPList;
objProvSum.DataSource = provList;
objInsuredPrice.ValueMember = objTPPrice.ValueMember = objProvSum.ValueMember = "Price";
objInsuredPrice.DisplayMember = objTPPrice.DisplayMember = objProvSum.DisplayMember = "Description";
objInsuredPrice.SelectedIndex = objTPPrice.SelectedIndex = objProvSum.SelectedIndex = 0;
【问题讨论】:
没有。我没有将任何事件连接到这些组合框。我真的把它们从工具箱拖到我的表单上,给它们一个名字,然后把上面的代码放在我的表单“加载”事件中。 这是微软团队的一个愚蠢的(以及所有暗示的)实现。是否有人认为组件 A 对组件 B 有任何影响是正确的行为,因为它们使用相同的输入列表?有人认为为每个组件制作整个列表的副本是一个合理的解决方案吗?感谢上帝,这个 WinForms 是死技术。现在,如果他们只能将 SilverLight 冲入下水道……哦,对了,他们做到了。 是的,如果您有多个使用公共列表的组件,它们相互影响是正常的。如果您想要单独的列表,请使用单独的列表。 【参考方案1】:也许你也可以试试这个解决方案,只需为第二个组合框分配一个新的上下文:
combobox1.DataSource = results;
combobox1.DisplayMember = "DisplayValue";
combobox1.ValueMember = "Value";
combobox2.BindingContext = new BindingContext(); //create a new context
combobox2.DataSource = results;
combobox2.DisplayMember = "DisplayValue";
combobox2.ValueMember = "Value";
谢谢
【讨论】:
Ivo 干得好,我一直在寻找一个很好的答案,只需最少的重构。谢谢。 出于性能原因,combobox.DataSource 应位于最后一行,在 ValueMember、DisplayMember 之后...【参考方案2】:我不明白为什么这应该这么难...您可以将它们链接到相同数据源的克隆...解决问题。你需要做的就是
objInsuredPrice.DataSource = new List<TSPrice>(priceList);
objTPPrice.DataSource = new List<TSPrice>(priceList);
objProvSum.DataSource = new List<TSPrice>(priceList);
顺便说一句,这正是 VVS 的代码所做的。
不过,奇怪的行为......这只是 是一个错误,imo。
【讨论】:
【参考方案3】:我知道你没有要求,但我可以建议你稍微重构一下你的最终代码 :-)
private List<TSPrice> GetPriceList()
return new List<TSPrice>
new TSPrice(0, ""),
new TSPrice(0, "Half Day"),
new TSPrice(0, "Full Day"),
new TSPrice(0, "1 + Half"),
new TSPrice(0, "2 Days"),
new TSPrice(0, "Formal Quote Required")
;
private void BindPriceList(ComboBox comboBox, List<TSPrice> priceList)
comboBox.DataSource = priceList();
comboBox.ValueMember = "Price";
comboBox.DisplayMember = "Description";
comboBox.SelectedIndex = 0;
BindPriceList(objInsuredPrice, GetPriceList());
BindPriceList(objTPPrice, GetPriceList());
BindPriceList(objProvSum, GetPriceList());
【讨论】:
好建议。我通常对重构非常敏感,但我正在对代码已经一团糟的古老软件进行一些小改进 - 所以感觉不值得让小块看起来漂亮哈哈。但是我已经采纳了您的建议并实施了,谢谢:) 重构方法的想法消除了很多混乱。让代码更干净!【参考方案4】:是的,你是正确的,因为你绑定到同一个源,所以选择一个将应用于组合框的其余部分
为了克服这个问题,您需要在 slectedindex 更改事件中手动删除其他组合框处理程序,然后设置选定索引,然后再次添加处理程序以放入代码,如下所示
ComboBox c1 = new ComboBox();
ComboBox c2 = new ComboBox();
c1.SelectedIndexChanged += new EventHandler(c1_SelectedIndexChanged);
c2.SelectedIndexChanged += new EventHandler(c2_SelectedIndexChanged);
void c2_SelectedIndexChanged(object sender, EventArgs e)
c1.SelectedIndexChanged -= c1_SelectedIndexChanged;
c2.SelectedIndex = 2;
c1.SelectedIndexChanged += c1_SelectedIndexChanged;
void c1_SelectedIndexChanged(object sender, EventArgs e)
c2.SelectedIndexChanged -= c2_SelectedIndexChanged;
c1.SelectedIndex = 2;
c2.SelectedIndexChanged += c2_SelectedIndexChanged;
【讨论】:
感谢您的回答!我没有使用您的代码,但是您确认将它们绑定到同一个 ListBeth Massi 写了一篇文章来解释这个问题和正确的解决方案: https://web.archive.org/web/20190114100843/https://blogs.msdn.microsoft.com/bethmassi/2007/09/19/binding-multiple-combo-boxes-to-the-same-data-source/
她还链接到了一系列关于数据绑定的其他视频。
我已经阅读了以前的答案,并且可以确认,遗憾的是,当我尝试它们时,它们都不起作用。
在组合框上创建一个新的 BindingContext 似乎会破坏它。我建议按照 Beth 的说明进行操作:进行全新的 BindingSource 设置。
【讨论】:
解决方法是:comboBox1.DataSource = new BindingSource() DataSource = yourList;
【参考方案6】:
这对我有用,我不需要复制源代码。
List<string> days = GetDays();
List<string> months = GetMonths();
List<string> years = GetYears();
Son1DDLDay.DataSource = days;
Son1DDLDay.DataBind();
Son1DDLMonth.DataSource = months;
Son1DDLMonth.DataBind();
Son1DDLYear.DataSource = years;
Son1DDLYear.DataBind();
Son2DDLDay.DataSource = days;
Son2DDLDay.DataBind();
Son2DDLMonth.DataSource = months;
Son2DDLMonth.DataBind();
Son2DDLYear.DataSource = years;
Son2DDLYear.DataBind();
【讨论】:
我相信 OP 的问题是关于 WinForms,但你是对的,ASP.Net 没有同样的问题。以上是关于具有相同数据源的多个组合框 (C#)的主要内容,如果未能解决你的问题,请参考以下文章