为什么组合框在创建时将其项目增加一倍?

时间:2018-12-26 03:17:39

标签: c# .net winforms data-binding combobox

我正在以编程方式创建一个组合框,如下所示:

var cbo = new ComboBox();
cbo.HandleCreated += (s, e) =>
{
    cbo.DataSource = mylist;
};

当我执行上述操作时,组合框将显示列表中包含的项的两倍。但是,当我执行以下操作时,组合框将显示正确数量的项目:

var cbo = new ComboBox() {
    DataSource = mylist
};

为什么会这样?

2 个答案:

答案 0 :(得分:3)

此代码重复了该记录,因为在您对组合框进行初始化时,它将触发事件 HandleCreated ,该事件会将您的列表添加到组合框中。然后,在完成初始化之后,代码的执行将再次击中事件 HandleCreated ,因为执行该事件的第一个事件来自初始化,第二个事件来自运行时执行本身。

var cbo = new ComboBox(); //initialization
//below this comment is the event
    cbo.HandleCreated += (s, e) =>
    {
        cbo.DataSource = mylist;
    };

P.S。

在C#WinForms中填充组合框有更好的方法。每个控件(组合框,文本框等)都有各自不同的事件。您可以先检查该事件,而不要创建活动。

答案 1 :(得分:1)

原因

  

HandleCreated仅加注一次。问题是另外一回事,这是因为OnHandleCreated和数据绑定已在ComboBox中实现。

ComboBox的{​​{3}}方法是这样工作的:

  • 它首先引发HandleCreated事件。 (请记住,IsHandleCreated在这一点上是正确的。)
  • 然后为控件Items集合中的每个项目发送一个OnHandleCreated 将项目添加到本机组合框的本机消息。

这是设置DataSource的工作方式:

  • 对于DataSource中的每个项目,它首先CB_ADDSTRING将该项目收集到Items,然后检查IsHandleCreated是否为真,发送一个CB_ADDSTRING 将项目添加到本机组合框的本机消息。

因此,当您在DataSource事件中设置HandleCreated时,对于每个项目,它都会发送两次CB_ADDSTRING本机消息。

这就是为什么您在下拉菜单中两次看到项目,同时Items.Count显示正确计数的原因。此外,如果您单击其他项目(项目的最后一半),则会收到索引超出范围异常。

解决方案

要解决此问题,可以使用以下任一视蛋白:

  1. 您可以使用HandleCreated

  2. 来延迟BeginInvoke事件代码的执行。
  3. 作为另一种选择,您可以依赖VisibleChanged事件。

选项1-HandleCreated + BeginInvoke

var mylist = Enumerable.Range(1, 5).ToList();
var myvalue = 2;
var cbo = new ComboBox();
cbo.HandleCreated += (obj, args) =>
{
    BeginInvoke(new Action(() =>
    {
        cbo.DataSource = mylist;
        cbo.SelectedIndex = mylist.IndexOf(myvalue);
    }));
};
this.Controls.Add(cbo);

选项2-可见更改

var mylist = Enumerable.Range(1, 5).ToList();
var myvalue = 2;
var cbo = new ComboBox();
cbo.VisibleChanged+= (obj, args) =>
{
    cbo.DataSource = mylist;
    cbo.SelectedIndex = mylist.IndexOf(myvalue);
};
this.Controls.Add(cbo);