问题
I have a ComboBox that is bound to a DataSource. I want to dynamically add items to the ComboBox based on certain conditions. So what I've done is add the options to a new list, and then change the DataSource of the ComboBox like so:
cbo.DataSource = null;
cbo.DataSource = cbos;
cbo.DisplayMember = "Title";
cbo.ValueMember = "Value";
Then, I check cbo.Items.Count, and it has not incremented - it does not equal the count of the DataSource. Any ideas what I can do here? Note this is WinForms and not asp.net.
Thanks
回答1:
Did you check the Count immediately or at a later time? There is the possibility that the ComboBox does not actually update it's contents until there is an operation such as a UI refresh and hence the count will be off until that time.
On case where this may happen is if you update the DataSource before the Handle is created for the ComboBox. I dug through the code a bit on reflector and it appears the items will not be updated in this case until the ComboBox is actually created and rendered.
回答2:
If anyone experiences this problem on a dynamically added combobox, the answer is to ensure that you add the combobox to the controls of a container in the form.
By adding "this.Controls.Add(cbo);" to the code before setting the datasource, the problem goes away.
回答3:
I've found the cause...
I took out the cbo.Datasource = null line.. and added a cbo.Invalidate() at the end. This has solved the problem.
Thanks all for the advice.
回答4:
cbo.DataSource = null;
cbo.DataSource = cbos;
cbo.DisplayMember = "Title";
cbo.ValueMember = "Value";
Now before setting cbo.SelectedValue, or relying on Items to be up-to-date, call
cbo.CreateControl ;
and Items will be re-calculated.
The problem is that SelectedValue/SelectedIndex, which are WinForms properties, only accept the values that are legal according to the Items list, but that one is built only after GUI interaction, i.e. after instantiating a "real" Windows GUI combo box, i.e. after obtaining a Windows handle for the combobox.
CreateControl forces the creation of the Windows handle, no matter what.
回答5:
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;
回答6:
Just to clarify are you calling the count() method After calling the databind() method
回答7:
This code produces 2 in the message box for me, can you try it and see how it behaves for you?
You can paste it into a console application, and add a reference to System.Windows.Forms and System.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;
}
}
}
}
回答8:
comboBox1.DataSource=somelist;
int c1=comboBox1.DataSource.Count; // still zero
BindingContext dummy = this.comboBox1.BindingContext;// Force update NOW!
int c2=comboBox1.DataSource.Count; // now it equals somelist.Count
回答9:
I had the same problem (Im working with VS 2005).
What you need to do is set the DataSource to null, clear the items, reassign the datasource , display and value members.
Eg
cbo.DataSource = null;
cbo.Items.Clear();
cbo.DataSource = cbos;
cbo.DisplayMember = "Title";
cbo.ValueMember = "Value";
回答10:
Old thread, but I tried some of these solutions, along with suspending/resuming the bindingcontext, binding to and resetting a binding source, and just plain reloading the form. None worked to update my control with the newly bound data at the time of my .datasource setting (my items.count was empty, just like the OP).
Then I realized that my combobox was on a tabpage that was getting removed at the start of the code, and later re-added (after my databinding). The binding event did not occur until the tabpage was re-added.
Seems obvious in retrospect, but it was very difficult to detect at runtime, due to the order of calls and inability to see when things were changing.
回答11:
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);
TO
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";
The DataSource, DisplayMember and ValueMember property must be set after the control has been added to its container.
回答12:
Try this code.
cbo.BindingContext = new BindingContext();
cbo.DataSource = null;
cbo.DataSource = cbos;
cbo.DisplayMember = "Title";
cbo.ValueMember = "Value";
Maybe your ComboBox`s BindingContext is null.
回答13:
Ba salam,
you can simply refresh the UI by preformLayout() function;
Example:
comboBox1.performLayout();
regards mohsen s
回答14:
please try this:
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);
I think your question sames like I met today.
来源:https://stackoverflow.com/questions/887803/combobox-items-count-doesnt-match-datasource-c