[英]C# Why isn't it possible to set the selectedValue of a dynamically created combobox?
我在类中创建了一个组合框,并希望为该组合框设置选定的值。 但是当我这样做时, selectedValue 保持为空,当我尝试设置 selectedIndex 时,我得到一个 ArgumentOutOfRangeException。
代码:
public Control GenerateList(Question question)
{
// Clear the local givenAnswer collection
_givenAnswer.Clear();
// Get a list with answer possibilities
List<QuestionAnswer> answers = question.GetAnswerSort();
// Get a collection of given answers
Collection<QuestionnaireAnswer> 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,它保持为空
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<Car> cars = new Collection<Car>();
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
- 也许组合框忽略了所有没有“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 尝试先将 cmb 添加到Form
之前分配SelectedIndex
。
编辑:
public Control GenerateCombo()
{
// Create datasource
Collection<Car> cars = new Collection<Car>();
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
设置值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.