Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice for synchronizing a changing List of the model to a ObservableList of the ViewModel?

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

  • Synchronizing Lists - Are there best practices (or frameworks) on how to do such a merge (Copy new items to ObservableCollection, Deleting missing ones, updating altered items)
  • Selected Item - How can I assure that the ListBox keeps the currently selected item (besides the case that item was removed)
like image 990
Seven Avatar asked Feb 26 '13 14:02

Seven


1 Answers

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.

like image 51
Arthur Nunes Avatar answered Oct 20 '22 18:10

Arthur Nunes