WinForms ComboBox数据绑定陷阱
时间:2020-03-05 18:37:21 来源:igfitidea点击:
假设我们正在执行以下操作
List<string> myitems = new List<string> { "Item 1", "Item 2", "Item 3" }; ComboBox box = new ComboBox(); box.DataSource = myitems; ComboBox box2 = new ComboBox(); box2.DataSource = myitems
因此,现在我们有2个组合框绑定到该数组,并且一切正常。但是,当我们更改一个组合框的值时,会将两个组合框都更改为我们刚刚选择的组合框。
现在,我知道数组总是通过引用传递的(了解到当我学习C:D时),但是为什么组合框会一起改变呢?我不相信组合框控件根本不会修改集合。
作为解决方法,这样做是否可以实现预期/期望的功能
ComboBox box = new ComboBox(); box.DataSource = myitems.ToArray();
解决方案:
这与在dotnet框架中,特别是在BindingContext中,如何设置数据绑定有关。从高层次上讲,这意味着如果没有另外指定,则每个表单和该表单的所有控件都共享相同的" BindingContext"。当我们设置" DataSource"属性时," ComboBox"将使用" BindingContext"来获取包装列表的" ConcurrenyMangager"。 " ConcurrenyManager"会跟踪诸如列表中当前选定位置之类的内容。
当我们设置第二个"组合框"的"数据源"时,它将使用相同的"绑定上下文"(窗体),这将产生与上述用于设置数据绑定的相同" ConcurrencyManager"的引用。
要获得更详细的解释,请参见BindingContext。
更好的解决方法(取决于数据源的大小)是声明两个" BindingSource"对象(从2.00开始新增),将集合绑定到这些对象,然后将它们绑定到组合框。
我附上一个完整的例子。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplication2 { public partial class Form1 : Form { private BindingSource source1 = new BindingSource(); private BindingSource source2 = new BindingSource(); public Form1() { InitializeComponent(); Load += new EventHandler(Form1Load); } void Form1Load(object sender, EventArgs e) { List<string> myitems = new List<string> { "Item 1", "Item 2", "Item 3" }; ComboBox box = new ComboBox(); box.Bounds = new Rectangle(10, 10, 100, 50); source1.DataSource = myitems; box.DataSource = source1; ComboBox box2 = new ComboBox(); box2.Bounds = new Rectangle(10, 80, 100, 50); source2.DataSource = myitems; box2.DataSource = source2; Controls.Add(box); Controls.Add(box2); } } }
如果我们想让自己更加困惑,请尝试始终在构造函数中声明绑定。这可能会导致一些非常奇怪的错误,因此我总是绑定在Load事件中。
这可能只是一个错字,但是在我们提供的代码中,我们在设置数据源时仅引用了第一个组合框:
ComboBox box = new ComboBox(); box.DataSource = myitems; ComboBox box2 = new ComboBox(); **box**.DataSource = myitems
未设置" box2"的数据源。