简体   繁体   中英

How do you refresh a combo box item in-place?

The ComboBox Items collection is an ObjectCollection, so of course you can store anything you want in there, but that means you don't get a Text property like you would with, say, a ListViewItem. The ComboBox displays the items by calling ToString() on each item, or using reflection if the DisplayMember property is set.

My ComboBox is in DropDownList mode. I have a situation where I want to refresh the item text of a single item in the list when it gets selected by the user. The problem is that the ComboBox doesn't re-query for the text at any time besides when it loads up, and I can't figure out how else to do what I want besides removing and re-adding the selected item like so:


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();

This code works fine, except for the fact that my SelectedIndex event ends up getting fired twice (once on the original user event, and then again when I re-set the property in this code). In this case, it's not a big deal that the event is fired twice, but it's inefficient, and I hate that. I could rig up a flag so it exits the event the second time, but that's hacking.

Is there a better way to get this to work?

肮脏的黑客:

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

Hmm... could you use a BindingList<T> , as described here ? That way, you could just modify the item in the underlying collection and have it reflected in the ComboBox without having to add or remove anything from the control.

You'd need to have a collection something like this, containing all your items for the ComboBox :

private BindingList<PlantComboBoxItem> plantComboBoxItems;

Then, at some point (like when the program is starting), bind it to the ComboBox :

cboPlants.DataSource = plantComboBoxItems;

Now, you can just modify the collection directly:

plantComboBoxItems[cboPlants.SelectedIndex].doWhateverYouWant();

And changes will be reflected in cboPlants . Is this what you're looking for?

Got it, using Donut's suggestion.

In form class:

private BindingList<PlantComboBoxItem> _plantList;

In loading method:

_plantList = new BindingList<PlantComboBoxItem>(plantItems);
cboPlants.DataSource = _plantList;

In SelectedIndexChanged event:

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

Thank you!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM