.NET WinForm ListBox item displays old value untill reassigned to itself
I populate a ListBox control with my own objects redefining ToString(). The objects are displayed cor开发者_如何学Crectly when I just add those objects using listBox1.Add(myObject). However, if I later change something in this object, no changes are displayed in the listbox. Debugging reveals that an object inside listBox1.Items is indeed changed, but it is not reflected on a screen.
Interestingly enough, if I reassign a particular listbox item to itself (sounds a bit weird, doesn't it?), like:
listBox1.Items[0] = listBox1.Items[0]
this line will display a correct value on screen.
What is going on here? Does it have anything to do with threading?
Since you're using ToString of the object to provide the text of the list box item, the ListBox has no idea that the value has changed. What you should do instead is have the object implement INotifyPropertyChanged then expose a public property such as Name or Text and return what you normally would have returned from ToString().
Then set the DisplayMember of the ListBox to the name of the new property.
Make sure you are correctly raising the PropertyChanged event in the object and the ListBox should be able to automatically pick up the changes.
Edit: Adrian's edit reminded me that I do believe you'll need to use a BindingList as your data source in order for the property change notifications to be picked up. A quick scan in Reflector looks like ListBox on its own will not pick up the property changes mentioned above. But INotifyPropertyChanged + BindingList should.
The ToString()
value of each item is cached when the listbox is first displayed. If an item in the listbox's Items
collection then changes, the listbox does not notice and still uses the cached ToString()
values for display. To force the listbox to update, either call RefreshItems()
to refresh all items, or call RefreshItem(int)
specifying the index of the item to refresh.
From the MSDN docs for RefreshItems()
:
Refreshes all ListBox items and retrieves new strings for them.
EDIT: It turns out that both of these methods are protected, so cannot be called externally. In trying to find a solution, I came across this SO question that this question is basically a duplicate of.
Have you tried calling Refresh()
on the ListBox? I think the problem is that the ListBox does not know your object changed. The reason reassigning the the item works is because the ListBox will repaint itself when the collection changes.
you could invalidate the control, forcing a re-paint... perhaps..
精彩评论