8

Mam (zewnętrzny) model eksponujący listę, która stale się zmienia (powiedzmy co dwie sekundy). ViewModel wie, że rejestracja listy dla zdarzeń PropertyChange. Ten ViewModel zapewnia również ObservableCollection dla interfejsu użytkownika dla powiązania danych.Najlepsza praktyka synchronizowania zmieniającej się listy modelu z obserwowalną listą ViewModel?

+-----------------------------------------------+ 
|           View| 
| +-----------+         | 
| |Listbox |         | 
| +-----------+         | 
+-----/\----------------------------------------+ 
     || 
     ||DataBinding 
     || 
     || 
+-----||----------------------------------------+ 
|  ||        ViewModel| 
| +--------------------+   +-------------+| 
| |ObservableCollection|<--------|ChangeHandler|| 
| +--------------------+ / +-------------+| 
|      /  ^  | 
+-------------------------/------------|--------+ 
         /   | 
         /   | 
      Synchronizing Lists   | PropertyChanged 
             | 
             | 
+--------------------------------------|--------+ 
|         +-----+ Model| 
|         |IList|  | 
|         +-----+  | 
|            | 
+-----------------------------------------------+ 

Zasadniczo działa to dobrze, oprócz aktualizacji przeprowadzanych stale. Przy każdej aktualizacji użytkownik traci swój wybór, tzn. Wszystkie pozycje zostaną odznaczone przy każdej aktualizacji. Nic dziwnego, ponieważ ListBox WPF "widzi", że została przypisana nowa lista.

Tak, sprawa musi być tak, że robimy nie przypisać nowy ObservableCollection, ale scalić zawartość bieżącego ObservableCollection z zaktualizowanym Model.List

teraz moje pytania

  • Synchronizowanie list - Czy istnieją dobre praktyki (lub schematy) dotyczące tego, jak wykonać scalenie? (Skopiuj nowe elementy do ObservableCollection, Usuwanie brakujących elementów, aktualizacja zmienionych elementów)
  • Wybrany element - W jaki sposób mogę zapewnić, że ListBox zachowuje aktualnie wybrany element (oprócz przypadku, w którym element został usunięty)
+4

+1 Ładny schemat =] –

+1

Dzięki. Jestem bardzo wizualną osobą i potrzebuję zdjęć. Szybko zrobić z Jave5 – Seven

Odpowiedz

2

Możesz wygenerować nową ObservableCollection z zaktualizowanej listy modeli lub zsynchronizować bieżącą ObservableCollection z wersją modelu.

Jeśli przejdziesz do drugiego, jedną rzeczą, której możesz chcieć uniknąć, jest wywołanie zdarzeń CollectChanged dla każdego zsynchronizowanego elementu. Spójrz na this ObservableCollection implementation, która ma trudności z odroczeniem powiadomień.

Jeśli chodzi o zachowanie bieżącego SelectedItem, jeśli instancja ObservableCollection nie została zmieniona (co jest prawdziwe, ponieważ synchronizujemy zbiory) i instancja SelectedItem nie została usunięta, pole listy powinno zawierać zaznaczenie. Nie jestem jednak pewien, czy to prawda, jeśli parametr NotifyCollectionChangedEventArgs.Action to "Reset". Jeśli tak jest, możesz użyć podejścia, którego używam, które ma mieć zarówno właściwość colllection, jak i właściwość SelectedItem w ViewModel. Powiązujesz SelectedItem ViewModel z trybem ListBox.SelectedItem w trybie TwoWay. Po zsynchronizowaniu kolekcji, zapisz SelectedItem w zmiennej tymczasowej, a następnie zastosuj ponownie, jeśli nie została usunięta, po synchronizacji.

+0

OK, dziękuję. Potwierdziłeś moje najgorsze wyobrażenia. Nie ma automatycznego scalania (dostarczanie własnego kompilatora). Nadszedł czas, aby napisać własną MergeableCollection z odroczonym podnoszeniem zdarzeń ;-) – Seven

+0

Obecnie pracuję nad rozwiązaniem podobnym do tego, co robisz z twoją kolekcją i korzystam z AutoMappera do mapowania między modelem domeny i modelem widoku . Jeśli to zrobisz, możesz napisać konwerter scalający, który automatycznie połączy przychodzące modele z kolekcji do kolekcji ViewModel. Znalazłem to całkiem przyjemne i łatwe w użyciu. [To pytanie] (http://stackoverflow.com/questions/12579328/merge-two-collectios-with-automapper-by-countition) jest podobne do tego, o czym mówię – Philter

Powiązane problemy