【问题标题】:WinForms ComboBox data binding gotchaWinForms ComboBox 数据绑定陷阱
【发布时间】:2010-09-05 06:07:46
【问题描述】:

假设您正在执行以下操作

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();

【问题讨论】:

    标签: c# winforms data-binding


    【解决方案1】:

    这与如何在 dotnet 框架中设置数据绑定有关,尤其是 BindingContext。在高层次上,这意味着如果您没有另行指定,则每个表单和表单的所有控件都共享相同的BindingContext。当您设置DataSource 属性时,ComboBox 将使用BindingContext 来获取包装列表的ConcurrenyMangagerConcurrenyManager 跟踪列表中的当前选定位置等内容。

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

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

    【讨论】:

    • 似乎付出了很多努力却没有提供任何好处并使数据绑定控件完全不直观。
    • 这解释了为什么会出现问题 - 但没有提出任何解决方案?
    【解决方案2】:

    更好的解决方法(取决于数据源的大小)是声明两个 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 事件中绑定。

    【讨论】:

    • 感谢您指出构造函数中的绑定会导致一些非常奇怪的错误。我遇到了类似的问题,我将代码移到了 Load 事件中,它显示了绑定的数据。
    • 我发现了一些最奇怪的未报告的错误。最坏的情况是组合框拒绝将其焦点返回给任何其他控件:D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-03
    • 2014-04-19
    • 2014-09-05
    • 1970-01-01
    • 1970-01-01
    • 2016-12-18
    相关资源
    最近更新 更多