Czy powinniśmy powiązać widok z właściwością modelu, czy ViewModel powinien mieć swoją własną?

21

Zaczynam projekt z następującym środowiskiem technicznym: .Net 4.0, Entity Framework 4.0, WPF z architekturą MVVM

Widziałem wiele przykładów w Internecie, kilka książek z tym środowiskiem. W niektórych przykładach autorzy mieli ten pomysł:

  1. Viemodel będzie miał instancję klasy Model (Entity Framework Entity np. Person)
  2. Powiąż formanty widoku WPF z właściwościami Modelu

Podczas gdy niektórzy autorzy:

  1. Viemodel ujawni wszystkie właściwości modelu.
  2. Powiąż formanty widoku WPF z właściwościami ViewModel, a nie bezpośrednio z modelem.

Więc czy dobrym pomysłem jest zezwolenie widokowi na powiązanie właściwości z modelu, a nie na pokazanie własnego modelu przez viewmodel? Lub który jest bardziej preferowany?

Pravin Patil
źródło
Osobiście uważam, że ujawnianie właściwości modelu powoduje dobre oddzielenie warstwy danych i warstw logicznych.
Alex Hope O'Connor,

Odpowiedzi:

25

Myślę, że wielu programistów najpierw próbuje zastosować skrót wiązania bezpośrednio do modelu, ale z mojego doświadczenia ma to pewne poważne wady. Podstawowym problemem jest to, że jeśli Twój model encji jest utrwalany przez NHibernate lub podobny, wtedy jak tylko View wyświetli właściwość modelu, NHibernate może zachować te zmiany w bazie danych. To nie działa dobrze na ekranach edycji, które mają przycisk Zapisz / Anuluj. W rzeczywistości może zdecydować się poczekać i zachować wszystko jako partię, ale pomysł jest taki, że kiedy zmieniasz model, popełniasz zmianę.

Tak więc nadal możesz uniknąć wiązania bezpośrednio do właściwości modelu na ekranach tylko do odczytu, ale wtedy będziesz mieć niespójność.

Ponadto większość modeli nie implementuje, INotifyPropertyChangedwięc mogą nie być odpowiednimi celami wiążącymi, jeśli stan ekranu zmieni się po pierwszym wyświetleniu.

Biorąc pod uwagę łatwość auto-właściwości, sugeruję, aby zawsze wiązać widok z ViewModel, a nie z modelem. Jest spójny, prosty i zapewnia największą elastyczność w zakresie wspierania zmian w przyszłości.

Scott Whitlock
źródło
Podoba mi się twoja odpowiedź. +1 za wzmiankę o ekranie edycji / zapisu. Ale wtedy zniechęcanie byłoby zapisywanie właściwości dwa razy - raz w modelu i jeszcze raz w widoku modelu. Wydłużyłoby to także czas programowania. Czy uważasz, że jest to uzasadnione ...?
Pravin Patil,
9
@Pravin Patil - fwiw, za każdym razem, gdy korzystałem z tego skrótu, przeklinałem się później, kiedy musiałem wrócić i go naprawić. Stosunkowo niewielki wysiłek polega na ponownym wdrożeniu właściwości ViewModel, szczególnie jeśli są one tylko do odczytu (ponieważ można użyć właściwości zaimplementowanych automatycznie z prywatnym ustawiaczem). Faktem jest, że w większości przypadków Model ma inną strukturę danych niż ViewModel. Pozostaw sobie swobodę zmiany modelu bez wpływu na widok. Im mniej musisz zmienić Widok, tym lepiej, ponieważ Widok jest trudny do przetestowania.
Scott Whitlock,
4
@ Scott Whitlock: Tworzę aplikacje WPF z NHibernate od dwóch lat i nigdy nie miałem żadnych problemów z bezpośrednim wiązaniem się z modelem. W rzeczywistości, gdy zmienia się właściwość modelu, jest to w większości ten sam wysiłek dla zmiany, niezależnie od tego, z czym się wiążesz. A kiedy naprawdę muszę później wykonać routing w samym ViewModel, nie warto było inwestować czasu, zanim go potrzebowałem. Stosuję podejście (jeszcze) YAGNI i nie mam żadnych trudności. Myślę, że ty i inni tutaj jesteście trochę dogmatyczni w tej kwestii.
Falcon,
16

Chodzi o ViewModelto, że jest to model View.

Powinieneś być wiążąca ViewModeldla View, już nie Modelwłaściwości (nie bezpośrednio, tak czy inaczej).

Oded
źródło
8

Uważam obie metody za dopuszczalne

Wiązanie tylko z ViewModel jest podejściem „purystycznym MVVM” i prowadzi do lepszego oddzielenia warstw. Wiązanie z modelem jest zwykle szybsze i wygodniejsze.

O ile nie mam dobrego powodu, aby w pełni oddzielić warstwy (rozmiar projektu, przyszłe problemy konserwacyjne, typ Modelu, nad którym pracuję itp.), Łączę się z Modelem.

Rachel
źródło
7

Myślę, że to, co widzisz, to koncepcja o nazwie bind through, to znaczy, jeśli twój model ma właściwość o nazwie name, a twój model widoku ujawnia tę właściwość bez dodatkowej edycji lub konwersji, wówczas możesz połączyć się z modelem, tak by to było.

Pseudo kod:

 {Binding: MyViewModel.MyModel.Name}

Ma to na celu zmniejszenie ilości właściwości „puchu” w modelu widoku, niestety jest to również zły pomysł na dłuższą metę. Koncepcja modelu widoku polega na zapewnieniu, że widok nie przyjmuje zależności od modelu. Powiązanie przez ciebie musi teraz zapewnić, że Twój model zawiera właściwość o nazwie name, w przeciwnym razie implementacja ulegnie awarii.

Jeśli jednak powiążesz tylko do modelu widoku, możesz go zmienić, a widok nigdy się nie dowie, ponieważ zobaczy tylko właściwość o nazwie Nazwa w modelu widoku.

Teraz można to złagodzić w pewnych okolicznościach, w których model oparty jest na interfejsie. Jeśli więc interfejs zawiera IBaseDetails, które ujawniają właściwość ModuleName, możesz:

Pseudo kod:

 {Binding: MyViewModel.MyModel.ModuleName}

Dopóki którykolwiek z twoich modeli spełnia interfejs IBaseDetails, twój złoty, pamiętaj jednak, że jest to wyjątkowy przypadek i ogólnie rzecz biorąc, zawsze jesteś o 90% lepszy, aby owinąć swój model widoku wokół wszystkich modeli, które obejmuje.

DeanMc
źródło
2

Jeśli widzisz duże tarcie próbujące przejść z Model -> ViewModel, spróbuj czegoś takiego jak AutoMapper. Usuwa ręcznie nudę związaną z kopiowaniem właściwości.

Bryan Boettcher
źródło
1

Przybyłem tu tylko dlatego, że miałem te same wątpliwości i przekonałem się, że zawsze będę wiązać się z widokiem modelu zamiast z modelem.

Przyjmij podejście Angular Reactive Form. Grupę formularzy tworzy się przy użyciu niektórych informacji wyświetlanych w Modelu widoku, ale później trzeba uzyskać dostęp do formularza. Wartości do pobrania wartości i skopiowania wartości do modelu za pomocą dowolnego mapera automatycznego lub ręcznego Myślę, że nie ma nic piękniejszego niż przejście do właściwości w modelu widoku, powiedzmy na przykład, że mam stronę widoku projektu, na której mam nazwę projektu, nazwa klienta itp.

Istnieje związek między projektem a klientem, ponieważ projekt ma klienta. Na tym poziomie nie powinienem więc przejmować się tą relacją, muszę tylko wizualnie pokazać nazwę projektu i nazwę klienta w widoku, więc umieściłem 2 właściwości w nazwie modelu projektu i nazwie klienta, aby powiązać kontrolki widoku z obydwoma je, później będę się martwił o podanie wartości tych właściwości w kodzie za pobraniem z jakiejkolwiek struktury modelu.

To samo może dotyczyć aktualizacji modelu w przypadku zapisu / anulowania, nie ma nic bardziej czystego.

Ivan Carmenates García
źródło
ten post jest raczej trudny do odczytania (ściana tekstu). Czy mógłbyś edytować go w lepszym kształcie?
komar
Proszę bardzo, zdrowie.
Ivan Carmenates García