组合框已经支持这一点。
将您的元素列表放入属性中DataSource
:
var persons = new List<Person>();
// ToDo: fill list with some values...
myComboBox.DataSource = persons;
在属性中输入DisplayMember
将代表用户应该看到的对象的属性。如果不设置,组合框将调用.ToString()
所选元素。
myComboBox.DisplayMember = "FullName";
在属性中输入ValueMember
您希望从代码中的对象接收的属性。如果不设置,组合框将返回对象本身。
myComboBox.ValueMember = "Born";
要从组合框中取出当前选定的对象,只需将属性SelectedValue
转换为所需的类型。
private void OnComboBoxFormatSelectedIndexChanged(object sender, EventArgs e)
{
DateTime born = (DateTime)comboBox.SelectedValue
}
分配后更改列表的更新
如果在将数据源分配给组合框后需要更改列表或其中的项目,则必须通知组合框有关此更改。最简单的方法是简单地将数据源重新分配给组合框:
myComboBox.DataSource = persons;
更简洁的方法是,如果列表本身可以在发生任何更改时触发事件。此功能由 实现,BindingList<T>
如果您通过添加或删除元素来更改列表,则组合框会自动更新。
信息流的下一步将是通知组合框是否更改了项目本身(在我们的示例中,例如一个人的姓氏)。要做到这一点,列表中的对象必须实现一个PropertyNameChanged
事件(在我们的示例中,这将是 LastNameChanged,因为属性名称将是 LastName),或者您必须INotifyPropertyChanged
在您的类中实现。如果您这样做并使用绑定列表,这些事件将自动转发到组合框,并且值也将在那里更新。
注意:在第一步中,aBindingList
和的使用NotifyPropertyChanged
效果很好,但是如果你要从另一个线程中更改列表或对象属性(导致跨线程异常),你真的会遇到麻烦。但也可以避免这种情况。
您只需要在 ComboBox 和 BindingList 之间再增加一层;一个BindingSource
。这可以暂停和恢复通知链,以便您可以从另一个线程更改列表:
var persons = new BindingList<Person>();
var bindingSource = new BindingSource();
bindingSource.DataSource = persons;
comboBox.DataSource = bindingSource;
// Suspend change the list from another thread,
// and resume on the gui thread.
bindingSource.SuspendBinding();
Task.Factory.StartNew(() => persons.Add(Person.GetRandomFromDatabase()))
.ContinueWith(finishedTask => bindingSource.ResumeBinding(),
TaskScheduler.FromCurrentSynchronizationContext());