WPF binding a list / collection of items to a ListBox, but UI not refreshing after items updated, Solved.
I'm just stupid. While I'd read a lot about using ObservableCollection<>
instead of List<>
, I just continued to ignore this suggestion and went following other suggestions, to no avail. Got back to my books and reread. It's pretty well explained that ObservableCollection<>
is a must use because List<>
doesn't provide the INotifyCollectionChange
interface needed for the ListBox
to update its display when the items change in the collection.
This is the updated code:
private ObservableCollection<StringWrapper> m_AppLog;
ObservableCollection<StringWrapper> Log { get { return m_AppLog; } }
Pretty simple, and doesn't require anything else (e.g. Refresh()). Because ObservableCollection takes care itself of triggering the change event, I was able to remove the unnecessary call:
// notify bound objects
OnPropertyChanged("Log");
ObservableCollection
doesn't support an update by a thread which didn't create it. Because my list (a visual log to show the recent errors/info messages) can be updated from different threads, I add to adjust my code this way to ensure the update was done with the list's own dispatcher:
public void AddToLog(string message) {
if (Thread.CurrentThread != Dispatcher.Thread) {
// Need for invoke if called from a different thread
Dispatcher.Invoke(
DispatcherPriority.Normal, (ThreadStart)delegate() { AddToLog(message); });
}
else {
// add this line at the top of the log
m_AppLog.Insert(0, new StringWrapper(message));
// ...
Also note that ObservableCollection<>
doesn't support RemoveRange()
contrary to List<>
. This is part of the possible adjustments required when switching from List to ObservableCollection.