如何在原地刷新组合框项目?

5
ComboBox的Items集合是一个ObjectCollection,所以你可以在里面存储任何你想要的东西,但这意味着你不会像ListViewItem那样拥有Text属性。ComboBox通过调用每个项的ToString()方法来显示项,或者如果设置了DisplayMember属性,则使用反射。
我的ComboBox处于DropDownList模式。我遇到了这样一种情况:当用户选择某个项目时,我希望刷新列表中单个项目的文本。问题是,除了加载时之外,ComboBox不会在任何其他时间重新查询文本,而且我无法找出如何实现我想要的效果,除非像这样删除并重新添加所选项目:

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

这段代码运行良好,除了一个问题,就是我的SelectedIndex事件会被触发两次(一次是在原始用户事件中,另一次是在我重新设置属性时)。在这种情况下,事件触发两次并不是什么大问题,但它是低效的,我很讨厌这样。我可以设置一个标志来在第二次退出事件,但那是hack的。

有没有更好的方法使它正常工作?

3个回答

11
一个不太正规的解决方法:
typeof(ComboBox).InvokeMember("RefreshItems", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, null, cboPlants, new object[] { });

4

嗯...你能使用BindingList<T>吗?就像这里所描述的那样。这样,您只需修改基础集合中的项目,就可以在ComboBox中反映出来,而无需向控件添加或删除任何内容。

您需要有一个类似于此的集合,其中包含所有ComboBox的项目:

private BindingList<PlantComboBoxItem> plantComboBoxItems;

然后,在某个时间点(比如程序启动时),将其绑定到 ComboBox 上:

cboPlants.DataSource = plantComboBoxItems;

现在,您可以直接修改集合:
plantComboBoxItems[cboPlants.SelectedIndex].doWhateverYouWant();

更改将反映在 cboPlants 中。这是您要寻找的吗?


3

明白了,采用Donut的建议。

在表单类中:

private BindingList<PlantComboBoxItem> _plantList;

在加载方法中:

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

在SelectedIndexChanged事件中:
int selectedIndex = cboPlants.SelectedIndex;
_plantList.ResetItem(selectedIndex);

谢谢!

顺便问一句,我想知道为什么没有人考虑在ComboBox中包含类似RefreshItem功能的东西。 - Jon Seigel
不要啊... ResetItem() 会触发 SelectedIndexChanged 方法 :( 嗯,这仍然比我的原始解决方案更干净。 - Jon Seigel
你需要调用 ResetItem() 吗?如果你直接更新 cboPlants 中的项目,它应该会被更改(我想是这样的吧?)。你可以在 SelectedIndexChanged 事件中通过 _plantList[selectedIndex] 访问它。 - Donut
是的,我必须调用ResetItem()。否则该控件无法刷新项目(我尝试删除这一行时,它不会在我更改项目时更新)。即使PlantComboBoxItem中的底层数据发生了变化,该项目也不会自动更新。我认为ResetItem()函数必须在内部实现为先手动删除,然后再添加项的操作,真是个大麻烦。 - Jon Seigel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接