Come si aggiorna un object casella combinata sul posto?

La collezione di oggetti ComboBox è un ObjectCollection, quindi ovviamente è ansible memorizzare tutto ciò che si desidera, ma ciò significa che non si ottiene una proprietà Text come si farebbe con, ad esempio, un object ListViewItem. ComboBox visualizza gli elementi chiamando ToString () su ciascun elemento o utilizzando reflection se la proprietà DisplayMember è impostata.

Il mio ComboBox è in modalità DropDownList. Ho una situazione in cui voglio aggiornare il testo dell’articolo di un singolo elemento nell’elenco quando viene selezionato dall’utente. Il problema è che il ComboBox non esegue nuovamente la query per il testo in qualsiasi momento, oltre a quando si carica, e non riesco a capire in che altro modo fare ciò che voglio, oltre a rimuovere e riaggiungere l’elemento selezionato in questo modo:

PlantComboBoxItem selectedItem = cboPlants.SelectedItem as PlantComboBoxItem; // ... cboPlants.BeginUpdate(); int selectedIndex = cboPlants.SelectedIndex; cboPlants.Items.RemoveAt(selectedIndex); cboPlants.Items.Insert(selectedIndex, selectedItem); cboPlants.SelectedIndex = selectedIndex; cboPlants.EndUpdate(); 

Questo codice funziona correttamente, tranne il fatto che il mio evento SelectedIndex finisce per essere sparato due volte (una volta sull’evento utente originale e poi di nuovo quando re-set la proprietà in questo codice). In questo caso, non è un grosso problema che l’evento venga licenziato due volte, ma è inefficiente, e io lo odio. Potrei mettere su una bandiera in modo che esca l’evento la seconda volta, ma questo è hacking.

C’è un modo migliore per farlo funzionare?

Un trucco sporco:

 typeof(ComboBox).InvokeMember("RefreshItems", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, null, cboPlants, new object[] { }); 

Hmm … potresti usare una BindingList , come descritto qui ? In questo modo, potresti semplicemente modificare l’elemento nella raccolta sottostante e farlo riflettere in ComboBox senza dover aggiungere o rimuovere nulla dal controllo.

Avresti bisogno di avere una collezione come questa, contenente tutti gli oggetti per il ComboBox :

 private BindingList plantComboBoxItems; 

Quindi, ad un certo punto (come quando il programma sta avviando), collegalo al ComboBox :

 cboPlants.DataSource = plantComboBoxItems; 

Ora puoi modificare direttamente la raccolta:

 plantComboBoxItems[cboPlants.SelectedIndex].doWhateverYouWant(); 

E i cambiamenti si rifletteranno in cboPlants . E ‘questo quello che stai cercando?

Capito, usando il suggerimento di Donut.

Nella class della forma:

 private BindingList _plantList; 

Nel metodo di caricamento:

 _plantList = new BindingList(plantItems); cboPlants.DataSource = _plantList; 

Nell’evento SelectedIndexChanged:

 int selectedIndex = cboPlants.SelectedIndex; _plantList.ResetItem(selectedIndex); 

Grazie!