C#为什么不能设置动态创建的combobox的selectedValue?

我在类中创建了一个combobox,并希望为该combobox设置选定的值。 但是当我这样做时,selectedValue保持为null,当我尝试设置selectedIndex时,我得到一个ArgumentOutOfRangeException。

码:

public Control GenerateList(Question question) { // Clear the local givenAnswer collection _givenAnswer.Clear(); // Get a list with answer possibilities List answers = question.GetAnswerSort(); // Get a collection of given answers Collection givenAnswers = question.GetGivenAnswers(); _givenAnswer = givenAnswers; ComboBox cmb = new ComboBox(); cmb.Name = "cmb"; cmb.DisplayMember = "Answer"; cmb.ValueMember = "Id"; cmb.DataSource = answers; cmb.Dock = DockStyle.Top; // Check an answer is given to the question if (givenAnswers != null && givenAnswers.Count > 0) { cmb.Tag = givenAnswers[0].AnswerId; cmb.SelectedValue = givenAnswers[0].AnswerId; // answerId = 55, but SelectedValue stays null } cmb.SelectedIndex = 1; // For testting. This will throw a ArgumentOutOfRangeException cmb.DropDownStyle = ComboBoxStyle.DropDownList; cmb.SelectedIndexChanged += new EventHandler(cmb_SelectedIndexChanged); return cmb; } 

我希望有人可以向我解释发生了什么,这样我就能理解为什么它不起作用。

这是一个完整的小程序,说明了我的问题。 正如您所看到的,它没有设置SelectedValue,它保持为null

 namespace Dynamic_Create_Combo { public partial class Form1 : Form { public Form1() { InitializeComponent(); GenerateControls gc = new GenerateControls(); Control c = gc.GenerateCombo(); this.SuspendLayout(); this.Controls.Add(c); this.ResumeLayout(true); } } public class GenerateControls { public Control GenerateCombo() { // Create datasource Collection cars = new Collection(); Car c = new Car(); c.Id = 1; c.Name = "Car one"; cars.Add(c); Car c1 = new Car(); c1.Id = 2; c1.Name = "Car two"; cars.Add(c1); Car c2 = new Car(); c2.Id = 2; c2.Name = "Car three"; cars.Add(c2); ComboBox cmb = new ComboBox(); cmb.DropDownStyle = ComboBoxStyle.DropDownList; cmb.DataSource = cars; cmb.DisplayMember = "Name"; cmb.ValueMember = "Id"; cmb.SelectedValue = 2; return cmb; } } public class Car { private int _id; private string _name; public int Id { get { return _id; } set { _id = value; } } public string Name { get { return _name; } set { _name = value; } } } } 

您已将值成员设置为“Id”,但您尝试使用“AnswerId”作为所选值。

没有更多细节,很难说为什么设置SelectedIndex会抛出ArgumentOutOfRangeException – 也许combobox忽略了所有没有“Id”属性的值,因此没有给你任何值,所以选择索引1是不可能的?

编辑:好的,所以它看起来只是在它变得可见时才实际进行绑定 – 或者在过程的某个阶段。 我已经尝试了一些方法来加速这一点,但它们似乎没有帮助。 您可以做的是推迟您的选择:

 EventHandler visibleChangedHandler = null; visibleChangedHandler = delegate { cmb.SelectedIndex = 2; cmb.VisibleChanged -= visibleChangedHandler; // Only do this once! }; cmb.VisibleChanged += visibleChangedHandler; 

这是一个丑陋的解决方法,但它至少应该帮助你暂时开始。

这只是一个猜测,但也许, ComboBox在绘制之前不会绑定DataSource中的DataSource 。 检查在SelectedIndex = 1之前的行中的cmb.Items.Count 。 如果为0,请尝试在分配SelectedIndex之前首先将cmb添加到Form

编辑:

  public Control GenerateCombo() { // Create datasource Collection cars = new Collection(); Car c = new Car(); c.Id = 1; c.Name = "Car one"; cars.Add(c); Car c1 = new Car(); c1.Id = 2; c1.Name = "Car two"; cars.Add(c1); Car c2 = new Car(); c2.Id = 2; c2.Name = "Car three"; cars.Add(c2); ComboBox cmb = new ComboBox(); cmb.DropDownStyle = ComboBoxStyle.DropDownList; cmb.DataSource = cars; cmb.DisplayMember = "Name"; cmb.ValueMember = "Id"; // add this: EventHandler visibleChangedHandler = null; visibleChangedHandler = delegate { cmb.SelectedIndex = 2; cmb.VisibleChanged -= visibleChangedHandler; }; cmb.VisibleChanged += visibleChangedHandler; // delete this: cmb.SelectedValue = 2; return cmb; } 

您需要设置cmb.DataBindings, 这可能会有所帮助。

也许是因为组合是在Form_load事件期间创建的。 尝试在构造函数中创建组合并在Form_Load中设置选择。

 public class Form1 { private ComboBox _comboBox1; private Car _audi = new Car("Audi)"); private Car _porsche = new Car("Porsche"); private Car _vw = new Car("VW"); private void Form1_Load(object sender, EventArgs e) { this._comboBox1.SelectedItem = _vw; } public Form1() { Load += Form1_Load; // This call is required by the designer. InitializeComponent(); // Add any initialization after the InitializeComponent() call. this._comboBox1 = new ComboBox(); this._comboBox1.DataSource = { _audi, _porsche, _vw }; this.Controls.Add(this._comboBox1); } private class Car { public string Name { get; set; } public override string ToString() { return this.Name; } public Car(name) { this.Name = name; } } } 

您可能想要尝试SelectedItem而不是SelectedValue ,并分配您想要的类。 例如:

 Car c1 = new Car(); // snip cmb.SelectedItem = c1; 

由于多个项目的值可以为2(无论如何, ComboBox知道),我认为您将难以通过SelectedValue 设置值。