Czy w MVVM ViewModel lub View powinny być odpowiedzialne za tworzenie nowych widoków?

11

W mojej aplikacji WPF chcę utworzyć nowy widok. Gdzie mam to zrobić - w ViewModel lub Model ?

Aplikacja jest (jak na razie bardzo prostym) narzędziem podobnym do jednego okna z pojedynczym przyciskiem „wyślij”. W przypadku zaznaczenia jednego z pól wyboru powinno pojawić się nowe okno z tym samym ViewModel, aby poprosić użytkownika o dodatkowe szczegóły. Na potrzeby tego pytania rozważmy tylko nowe podejście do okna bez rozważania innych podejść, takich jak pokazany / ukryty panel.

Idealnie byłoby, gdyby w widoku nie było żadnego kodu. Ponadto, ponieważ View nie ma w sobie żadnej logiki, VM musiałoby początkowo sprawdzić, czy konieczne jest utworzenie nowego widoku, i - gdy jest - odesłać tę odpowiedzialność z powrotem do View, co prowadzi do rozdęcia kodu.

Z drugiej strony, tworzenie nowego widoku w ViewModel narusza zasadę, że ViewModel nie powinien wiedzieć o View.

Czy lepiej tworzyć nowe widoki w View lub ViewModel?

Mac70
źródło
1
Naprawdę nie rozumiem twojego pytania. Co oznacza „In View lub ViewModel”? ViewModels nie tworzą widoków, a widoki z pewnością nie tworzą się same.
Robert Harvey
1
Mam na myśli, która z tych warstw powinna być odpowiedzialna za tworzenie nowych widoków - sygnał do zrobienia musi pochodzić skądś, gdy nastąpi akcja. Całkowicie wykluczyłem model z tego pytania, ponieważ nie powinien on w ogóle nic wiedzieć o frontendzie.
Mac70
Może nie rozumiem poprawnie twojego pytania, oba nie powinny kolidować z twoim poglądem. Jeśli chcesz utworzyć nowy widok w viewModel, czy istnieje jakiś powód, dla którego nie używasz ramek w xaml do zmiany zawartości okna z powiązaniem z bieżącym viewModel?
Siobhan

Odpowiedzi:

8

Używam wstrzykiwania zależności i IViewFactorywstrzykiwanego do modelu widoku, aby przestrzegać obu ograniczeń.

A ProductViewModel(na przykład) wzywa this.viewFactory.Show("Details", this)do otwarcia się ProductDetailsViewze sobą jako ProductViewModel. Może również otworzyć widok oparty na innym modelu widoku za pomocą this.viewFactory.Show<ClientViewModel>().

Implementacja (w rzeczywistości jest ich kilka dla WinForm, proste Wpf Windows, powłoka Wpf z kartami, ...) oparta jest na StructureMapkonwencji. Widoki oznaczają ich model widoku za pośrednictwem IView<ProductViewModel>interfejsu.

Zatem model widoku nie wie nic o widoku oprócz jego roli (widok domyślny, widok szczegółów, ...), a widok nie zawiera kodu do utworzenia innego widoku. Ponadto modele widoków znajdują się w osobnym zestawie, który nie odwołuje się do żadnego zestawu Wpf.

Philippe
źródło
7

Teoretyczna odpowiedź

Jeśli masz ViewModel, akcje, które mają efekty kosmetyczne (np. Podświetlenie elementu po najechaniu myszką) są zadaniem View, podczas gdy akcje, które mają „rzeczywiste” efekty (np. Odrodzenie nowego okna), są zadaniem ViewModel.

W związku z tym utworzenie nowego okna jest zadaniem dla ViewModel. Jednak ani widok, ani nie ViewModelpowinni wiedzieć, jak dokładnie utworzyć okno, co nie należy do ich obowiązków i należy do innej klasy.

Można argumentować, że utworzenie nowego okna jest zadaniem View. Chociaż nie zgadzam się, taka debata ma niewielką wartość, ponieważ w praktyce umieszczenie tego kodu w kodzie nie jest końcem świata View, a przeniesienie go ViewModelna później nie jest zbyt trudne . Ważną częścią jest to, że logika tworzenia nowego okna jest zawarta w niezależnej klasie, zwykle pewnego rodzaju WindowFactory. Istotą MVVM, MVP, MVC itp. Jest to, że masz zajęcia z niewielką liczbą dobrze określonych obowiązków. Dlatego nie należy dodawać dodatkowe obowiązki do View, ViewModellub Modeljeśli nie trzeba.

W żadnym wypadku tworzenie okna nie należy do Model, ponieważ Modelnawet nie zdaje sobie sprawy, że istnieje coś takiego jak GUI.

Praktyczna odpowiedź

Chodzi o „narzędzie podobne do formularza w jednym oknie z pojedynczym przyciskiem„ wyślij ” . Oto więc bezwstydna wtyczka do mojej podobnej odpowiedzi: Dlaczego warto korzystać z MVVM?

Podsumowując, co mówi ta odpowiedź: Uprość to. Aha, i pamiętaj o teoretycznej odpowiedzi powyżej, aby wdrożyć, gdy okno jednego przycisku zacznie się bardziej skomplikować.

Piotr
źródło