WinForms组合框数据绑定陷阱

假设你正在做类似下面的事情

List myitems = new List
{
    "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();
0
额外 编辑
意见: 2

3 答案

这与如何在dotnet框架中设置数据绑定有关,特别是 BindingContext 。在高层次上,这意味着如果你没有另外指定每个表单和表单的所有控件共享相同的 BindingContext 。当您设置 DataSource 属性时, ComboBox 将使用 BindingContext 来获取包装列表的 ConcurrenyMangagerConcurrenyManager 跟踪诸如列表中当前所选位置之类的事物。

当您设置第二个 ComboBoxDataSource 时,它将使用相同的 BindingContext (表单),它将产生对相同 ConcurrencyManager 用于设置数据绑定。

要获得更详细的解释,请参阅 BindingContext

0
额外
看起来像很多努力没有提供任何好处,并使数据绑定控件完全违反直觉。
额外 作者 Belmiris,

一个更好的解决方法(取决于数据源的大小)是声明两个 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 myitems = new List
            {
                "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);
        }
    }
}

如果你想更加迷惑自己,那就试着总是在构造函数中声明绑定。这可能导致一些真正好奇的bug,因此我总是在Load事件中绑定。

0
额外
我发现了一些最奇怪的未报告的错误。最糟糕的情况是组合框拒绝将其重点放回任何其他控制:D
额外 作者 Quibblesome,
感谢您指出在构造函数中的绑定导致一些真正好奇的错误。我有类似的问题,我将我的代码移动到Load事件,并显示绑定的数据。
额外 作者 bunggo,

这可能只是一个错字,但在您提供的代码中,只有在设置数据源时才引用第一个组合框:

ComboBox box = new ComboBox();
box.DataSource = myitems;

ComboBox box2 = new ComboBox();
**box**.DataSource = myitems

未设置 box2 的数据源。

0
额外