コンボボックスはすでにこれをサポートしています。
要素のリストをプロパティに入れます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
イベントを実装するか (この例では、プロパティ名が LastName であるため LastNameChanged になります) 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());