I have an (external) model exposing a List that constantly changes (let's say every two seconds or so). A ViewModel knows that list registering for PropertyChange events. That ViewModel also provides an ObservableCollection to the UI for data binding.
+-----------------------------------------------+
| View|
| +-----------+ |
| |Listbox | |
| +-----------+ |
+-----/\----------------------------------------+
||
||DataBinding
||
||
+-----||----------------------------------------+
| || ViewModel|
| +--------------------+ +-------------+|
| |ObservableCollection|<--------|ChangeHandler||
| +--------------------+ / +-------------+|
| / ^ |
+-------------------------/------------|--------+
/ |
/ |
Synchronizing Lists | PropertyChanged
|
|
+--------------------------------------|--------+
| +-----+ Model|
| |IList| |
| +-----+ |
| |
+-----------------------------------------------+
In principle that works well, besides the updates conducted constantly. With every update the user looses his selection, i.e. all items will be deselected with every update. This is no wonder, as WPF's ListBox "sees" that a new list was assigned.
So, the thing must be that we do not assign a new ObservableCollection, but merge the content of the current ObservableCollection with the updated Model.List
Now my questions
You can either generate a new ObservableCollection from the updated model list or sync the current ObservableCollection with the model's one.
If you go for the second, one thing you may want to avoid is to fire CollectionChanged events for every synced item. Take a look at this ObservableCollection implementation which has the hability to defer the notifications.
As for keeping the current SelectedItem, if the instance of the ObservableCollection isn't changed (what is true, because we are syncing the collections) and the SelectedItem instance isn't removed, the listbox should hold the selection. However, I'm not certain if that is true if the NotifyCollectionChangedEventArgs.Action is "Reset". If that's the case, you can use the approach I use, which is to have both a colllection property and a SelectedItem property in the ViewModel. You bind the ViewModel's SelectedItem to the ListBox.SelectedItem in TwoWay mode. When you synchronize the Collections, you save the SelectedItem in a temp variable and then reapply it, if it wasn't removed, after the synchronization.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With