Pomoc przy złożonym MVVM (wiele widoków)

18

Potrzebuję pomocy w tworzeniu modeli widoku dla następującego scenariusza:

  1. Głębokie, hierarchiczne dane
  2. Wiele widoków dla tego samego zestawu danych
  3. Każdy widok jest pojedynczym, dynamicznie zmieniającym się widokiem, opartym na aktywnym zaznaczeniu
  4. W zależności od wartości właściwości wyświetl różne typy kart w kontrolce kart

wprowadź opis zdjęcia tutaj

Moje pytania:

Czy powinienem utworzyć reprezentację modelu widoku dla każdego widoku (VM1, VM2 itp.)?

1. Yes:
    a. Should I model the entire hierarchical relationship? (ie, SubVM1, HouseVM1, RoomVM1)
    b. How do I keep all hierarchies in sync? (e.g, adding/removing nodes)

2. No:
    a. Do I use a huge, single view model that caters for all views?

Oto przykład jednego widoku

Rysunek 1: Zaktualizowano wiele widoków w oparciu o aktywny pokój. Kontrola karty powiadomień

wprowadź opis zdjęcia tutaj

Rysunek 2: Różne aktywne pomieszczenie. Zaktualizowano wiele widoków. Elementy sterujące tabulatorami zmieniono na podstawie właściwości obiektu.

wprowadź opis zdjęcia tutaj

Rysunek 3: Inny typ wyboru. Całe zmiany widoku

wprowadź opis zdjęcia tutaj

jayars
źródło
btw co to jest widok wielu? literówka?
JensG
„Widok Muliego” był literówką. Miałem na myśli różne widoki dla tego samego modelu / modelu widoku. Moje pytanie brzmiało: czy powinienem przebudować / zawinąć całą hierarchię modelu dla każdego widoku, aby każdy model widoku zawierał tylko to, czego potrzebuje pojedynczy widok? Czy powinienem utworzyć hierarchię modeli z jednym widokiem, która zawiera właściwości ze wszystkich widoków? Od kiedy opublikowałem to pytanie, miałem (nie) szczęście, że mogłem znaleźć zalety / wady tych dwóch problemów. Zaktualizuję ten wątek w przyszłości z pełną diagnozą mojego doświadczenia, gdy sprawy nie będą już tak gorączkowe.
jayars
Pamiętaj, że zasada projektowania polega na tym, aby najpierw pokazać rzeczy ogólne, a następnie przejść do szczegółów. pozostawi Ci jasny widok, a jeśli użytkownik wejdzie głębiej, pojawią się nowe widoki. więc używaj małych widoków wraz z ich odrębnymi modelami widoku. sprawdź interfejs projektu
Csharls,
@ jsjslim Zadrżałam, gdy przeczytałam: „Synchronizuj wszystkie hierarchie”. Podejrzewam, że poszedłeś z wieloma widokami i podejrzewam, że żałowałeś (ale wcześniej się myliłem). Ze względu na innych czytelników, którzy mogą mieć to samo pytanie, czy możesz przynajmniej dać nam szybką (ish) odpowiedź?
Guy Schalnat
2
@ guy-schalnat Multi-view był wymagany. Mój problem polegał na tym, aby dowiedzieć się, jak zbudować modele widoków. Projekt jest wciąż w toku i nie mogę znaleźć czasu na napisanie pełnej analizy. Podsumowując: powinienem był zignorować strukturę modelu i skupić się na widokach. Złożoność, na którą się natknąłem, była narzucona przez siebie: tak bardzo chciałem użyć powiązania danych WPF, że zostałem naprawiony. To, co ostatecznie zrobiłem, było dobre, stare „kopiowanie / wklejanie / refaktoryzacja”. Ostateczny projekt, który się pojawił, był lekki (mało powtórzeń), a co ważniejsze, działał. W przyszłości napisze pełną analizę.
jayars,

Odpowiedzi:

13

Aby odpowiedzieć na pytanie: Tak, każdy widok powinien mieć własny model widoku. Ale nie ma potrzeby modelowania całej hierarchii. Tylko to, czego potrzebuje widok.

Problem, który miałem z większością zasobów internetowych dotyczących MVVM:

W większości przykładów widok jest prawie odwzorowaniem modelu w stosunku 1 do 1. Ale w moim scenariuszu, w którym istnieją różne widoki dla różnych aspektów tego samego modelu, utknąłem między dwiema opcjami:

Jeden monolityczny model widoku używany przez wszystkie inne modele widoku

wprowadź opis zdjęcia tutaj

Lub jeden model widoku dla każdego widoku

wprowadź opis zdjęcia tutaj

Ale oba nie są idealne.

Model widokowy zorientowany na model (MVM), mimo niskiego poziomu duplikacji kodu, jest koszmarem do utrzymania

Model widoku zorientowany na widok (VVM) tworzy wysoce wyspecjalizowane klasy dla każdego widoku, ale zawiera duplikaty.

Ostatecznie zdecydowałem, że posiadanie jednej maszyny wirtualnej na widok jest łatwiejsze w utrzymaniu i kodowaniu, więc zdecydowałem się na podejście VVM.

Gdy kod działa, zacząłem refaktoryzować wszystkie typowe właściwości i operacje do jego obecnej, końcowej postaci:

wprowadź opis zdjęcia tutaj

W tej ostatecznej formie klasa wspólnego modelu widoku składa się z każdej VVM.

Oczywiście nadal muszę zdecydować, co jest uważane za wspólne / specjalistyczne. A gdy widok zostanie dodany / scalony / usunięty, to saldo się zmienia.

Ale fajną rzeczą jest to, że jestem teraz w stanie przesuwać członków w górę / w dół ze wspólnego do VVM i odwrotnie.

I krótka uwaga na temat synchronizacji obiektów:

Posiadanie modelu wspólnego widoku zajmuje się większością tego. Każda VVM może po prostu mieć odniesienie do tego samego modelu widoku wspólnego.

Zaczynam też od prostych metod wywołania zwrotnego i ewoluuję do zdarzenia / obserwatora, jeśli pojawi się potrzeba wielu słuchaczy.

W przypadku naprawdę skomplikowanych zdarzeń (tj. Nieoczekiwanych aktualizacji kaskadowych) przejdę na używanie Mediatora.

Nie unikam kodu, w którym dziecko ma odniesienie do swojego rodzica. Wszystko, żeby kod działał.

A jeśli pojawi się okazja do refaktoryzacji, skorzystam z niej.

Lekcje, których się nauczyłem:

  1. Kod brzydki / roboczy> Piękny / niedziałający kod
  2. Łatwiej jest połączyć wiele małych klas, niż rozbić ogromną klasę
jayars
źródło
Chciałbym móc to zagłosować dwa razy. To jedno z najjaśniejszych wyjaśnień opcji, które widziałem.
Clever Human
3

Patrząc na twoje makiety, zdecydowanie polecam stworzenie hierarchii ViewModels i wielu małych widoków. I najprawdopodobniej będziesz musiał modelować całkiem sporo oryginalnej hierarchii.

Aby zachować synchronizację między ViewModels, użyj albo zdarzeń, albo miej właściwości między sobą między ViewModels. Synchronizacja między widokami i modelami ViewModels powinna być standardowymi właściwościami powiadamiającymi.

Euforyk
źródło