ComboBox items.count与数据源不匹配(C#)

时间:2009-05-20 13:11:40

标签: c# winforms data-binding combobox

我有一个绑定到DataSource的ComboBox。我想根据特定条件动态添加项目到ComboBox。所以我所做的是将选项添加到新列表,然后像这样更改ComboBox的DataSource:

cbo.DataSource = null;
cbo.DataSource = cbos;
cbo.DisplayMember = "Title";
cbo.ValueMember = "Value";

然后,我检查cbo.Items.Count,它没有增加 - 它不等于DataSource的计数。我能在这做什么想法?注意这是WinForms而不是asp.net。

谢谢

14 个答案:

答案 0 :(得分:12)

您是否立即或稍后检查了伯爵? ComboBox有可能实际上没有更新它的内容,直到有一个操作,如UI刷新,因此计数将关闭,直到那个时间。

如果在为ComboBox创建句柄之前更新DataSource,则可能发生这种情况。我在反射器上挖了一些代码,看起来在这种情况下不会更新项目,直到实际创建和渲染ComboBox。

答案 1 :(得分:6)

如果有人在动态添加的组合框中遇到此问题,答案是确保将组合框添加到表单中容器的控件。

添加“this.Controls.Add(cbo);”在设置数据源之前的代码中,问题就消失了。

答案 2 :(得分:5)

我找到了原因......

我取出了cbo.Datasource = null行..并在最后添加了一个cbo.Invalidate()。这解决了这个问题。

感谢大家的建议。

答案 3 :(得分:4)

cbo.DataSource = null; 
cbo.DataSource = cbos; 
cbo.DisplayMember = "Title"; 
cbo.ValueMember = "Value"; 

现在,在设置cbo.SelectedValue或依赖Items进行更新之前,请致电

cbo.CreateControl ;

Items将重新计算。

问题是SelectedValue / SelectedIndex,它们是WinForms属性,只接受根据Items列表合法的值,但是只有在GUI交互之后才构建一个,即在实例化“真正的”Windows GUI组合框之后,即在获得组合框的Windows句柄之后。

CreateControl强制创建Windows句柄,无论如何。

答案 4 :(得分:1)

By adding "this.Controls.Add(cbo);" to the code before setting the datasource, the problem goes away.   
 //Create dynamic combobox and add to Panel
    ComboBox ddCombo = new ComboBox();
    controls = new Control[1] { ddCombo };
    panel.Controls.AddRange(controls); 

    //After creating add to table layout
    tableLayoutPanel.Controls.Add(panel, 0, 0);

    ddCombo .Name = "ddName";
    ddCombo .Width = 200;
    ddCombo .Location = new Point(x, y);                                                                                                          ddCombo .DataSource = ds;//or any List
    ddCombo .SelectedIndex = ddCombo .Items.Count - 1;

答案 5 :(得分:0)

我遇到了同样的问题(我正在使用VS 2005)。

您需要做的是将DataSource设置为null,清除项目,重新分配数据源,显示和评估成员。

例如

cbo.DataSource = null;

cbo.Items.Clear();

cbo.DataSource = cbos;

cbo.DisplayMember =“Title”;

cbo.ValueMember =“Value”;

答案 6 :(得分:0)

尝试此代码。

cbo.BindingContext = new BindingContext();
cbo.DataSource = null;
cbo.DataSource = cbos;
cbo.DisplayMember = "Title";
cbo.ValueMember = "Value";

也许您的ComboBox的BindingContext为空。

答案 7 :(得分:0)

旧线程,但我尝试了其中一些解决方案,以及挂起/恢复bindingcontext,绑定和重置绑定源,只是简单地重新加载表单。在我的.datasource设置时,没有人使用新绑定的数据更新我的控件(我的items.count为空,就像OP一样)。

然后我意识到我的组合框位于代码开头被删除的标签页上,后来重新添加(在我的数据绑定之后)。 之前没有发生绑定事件,直到重新添加标签页。

回想起来似乎很明显,但由于调用顺序和无法确定事情何时发生变化,在运行时很难检测到。

答案 8 :(得分:0)

只是为了澄清你是否在调用count()方法 调用databind()方法后

答案 9 :(得分:0)

 ComboBox cbNew = new ComboBox();
    cbNew.Name = "cbLine" + (i+1);
    cbNew.Size = cbLine1.Size;
    cbNew.Location = new Point(cbLine1.Location.X, cbLine1.Location.Y + 26*i);
    cbNew.Enabled = false;
    cbNew.DropDownStyle = ComboBoxStyle.DropDownList;
    cbNew.DataSource = DBLayer.GetTeams(lineName).Tables[0];
    cbNew.DisplayMember = "teamdesc";
    cbNew.ValueMember = "id";
    Console.WriteLine("ComboBox {0}, itemcount={1}", cbNew.Name, cbNew.Items.Count);
        // The output displays itemcount = 0 for run-time created controls
        // and >0 for controls created at design-time
    gbLines.Controls.Add(cbNew);

 ComboBox cbNew = new ComboBox();
    cbNew.Name = "cbLine" + (i+1);
    cbNew.Size = cbLine1.Size;
    cbNew.Location = new Point(cbLine1.Location.X, cbLine1.Location.Y + 26*i);
    cbNew.Enabled = false;
    cbNew.DropDownStyle = ComboBoxStyle.DropDownList;
    Console.WriteLine("ComboBox {0}, itemcount={1}", cbNew.Name, cbNew.Items.Count);
        // The output displays itemcount = 0 for run-time created controls
        // and >0 for controls created at design-time
    gbLines.Controls.Add(cbNew);
    cbNew.DataSource = DBLayer.GetTeams(lineName).Tables[0];
    cbNew.DisplayMember = "teamdesc";
    cbNew.ValueMember = "id";

将控件添加到容器后,必须设置DataSource,DisplayMember和ValueMember属性。

答案 10 :(得分:0)

此代码在消息框中为我生成2,您可以尝试一下并查看它的行为吗?

您可以将其粘贴到控制台应用程序中,并添加对System.Windows.FormsSystem.Drawing的引用。

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;

namespace SO887803
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.Run(new MainForm());
        }
    }

    public partial class MainForm : Form
    {
        private Button _Button;
        private ComboBox _ComboBox;

        public MainForm()
        {
            _Button = new Button();
            _Button.Text = "Test";
            _Button.Location = new Point(8, 8);
            _Button.Click += _Button_Click;
            Controls.Add(_Button);

            _ComboBox = new ComboBox();
            _ComboBox.Location = new Point(8, 40);
            Controls.Add(_ComboBox);
        }

        private void _Button_Click(object sender, EventArgs e)
        {
            List<Item> items = new List<Item>();
            items.Add(new Item("A", "a"));
            items.Add(new Item("B", "b"));

            _ComboBox.DataSource = null;
            _ComboBox.DataSource = items;
            _ComboBox.DisplayMember = "Title";
            _ComboBox.ValueMember = "Value";
            MessageBox.Show("count: " + _ComboBox.Items.Count);
        }

        public class Item
        {
            public String Title { get; set; }
            public String Value { get; set; }
            public Item(String title, String value)
            {
                Title = title;
                Value = value;
            }
        }
    }
}

答案 11 :(得分:0)

comboBox1.DataSource = somelist;

int c1 = comboBox1.DataSource.Count; //仍为零

BindingContext dummy = this.comboBox1.BindingContext; //现在强制更新!

int c2 = comboBox1.DataSource.Count; //现在它等于somelist.Count

答案 12 :(得分:-1)

请试试这个:

cbo.Parent = <your panel control>;
cbo.DataSource = null; 
cbo.DataSource = cbos; cbo.DisplayMember = "Title"; 
cbo.ValueMember = "Value";
MessageBox.Show(string.Format("itemcount is {0}", cbo.Items.Count);

我认为你的问题就像我今天遇到的一样。

答案 13 :(得分:-1)

巴拉姆,

您只需通过preformLayout()函数刷新UI;

示例:

comboBox1.performLayout();

问候 mohsen s