Czy ortodoksyjne wdrażanie MVVM jest bezcelowe? Tworzę nową aplikację i rozważałem Windows Forms i WPF. Wybrałem WPF, ponieważ jest przyszłościowy i zapewnia dużą elastyczność. Jest mniej kodu i łatwiej jest wprowadzać istotne zmiany w interfejsie użytkownika przy użyciu języka XAML.
Ponieważ wybór WPF jest oczywisty, doszedłem do wniosku, że równie dobrze mogę przejść całą drogę, używając MVVM jako mojej architektury aplikacji, ponieważ oferuje ona mieszalność, problemy z separacją i testowalność jednostkową. Teoretycznie wydaje się piękny jak Święty Graal programowania interfejsu użytkownika. Ta krótka przygoda; jednak zamienił się w prawdziwy ból głowy. Zgodnie z oczekiwaniami w praktyce stwierdzam, że zamieniłem jeden problem na inny. Mam tendencję do bycia programistą obsesyjnym, ponieważ chcę robić rzeczy we właściwy sposób, aby uzyskać właściwe wyniki i być może zostać lepszym programistą. Wzorzec MVVM właśnie oblał mój test produktywności i właśnie zmienił się w wielki ohydny hack!
Jasnym przykładem jest dodanie obsługi modalnego okna dialogowego. Prawidłowym sposobem jest wyświetlenie okna dialogowego i powiązanie go z modelem widoku. Uruchomienie tego jest trudne. Aby skorzystać z wzorca MVVM, musisz rozprowadzić kod w kilku miejscach w warstwach aplikacji. Musisz także używać ezoterycznych konstrukcji programistycznych, takich jak szablony i wyrażenia lamba. Rzeczy, które sprawiają, że gapisz się na ekran drapiąc się po głowie. To sprawia, że konserwacja i debugowanie są koszmarem czekającym, jak niedawno odkryłem. Miałem okno około działające dobrze, dopóki nie dostałem wyjątku przy drugim wywołaniu, mówiąc, że nie może ponownie wyświetlić okna dialogowego po zamknięciu. Musiałem dodać procedurę obsługi zdarzeń dla funkcji zamykania okna dialogowego, inny w implementacji IDialogView i wreszcie inny w IDialogViewModel. Myślałem, że MVVM uratuje nas przed tak ekstrawaganckim hakowaniem!
Jest kilka osób z konkurencyjnymi rozwiązaniami tego problemu i wszystkie są hackami i nie zapewniają czystego, łatwego do ponownego użycia, eleganckiego rozwiązania. Większość zestawów narzędzi MVVM prześwietla okna dialogowe, a kiedy je rozwiązują, są po prostu oknami ostrzegawczymi, które nie wymagają niestandardowych interfejsów ani modeli widoku.
Planuję zrezygnować z wzorca widoku MVVM, a przynajmniej jego ortodoksyjnej implementacji. Co myślisz? Czy warto było, gdybyś miał jakieś kłopoty? Czy jestem tylko niekompetentnym programistą, czy też MVVM nie jest tym, czym ma być?
Odpowiedzi:
Przepraszam, jeśli moja odpowiedź stała się trochę dłuższa, ale nie wiń mnie! Twoje pytanie również jest długie.
Podsumowując, MVVM nie jest bezcelowe.
Tak, naprawdę jest.
Jednak MVVM zapewnia sposób oddzielenia wyglądu interfejsu użytkownika od jego logiki. Nikt nie zmusza cię do używania go wszędzie i nikt nie trzyma pistoletu przy twoim czole, aby stworzyć osobny ViewModel do wszystkiego.
Oto moje rozwiązanie dla tego konkretnego przykładu:
Sposób, w jaki interfejs użytkownika obsługuje określone dane wejściowe, nie należy do firmy ViewModel. Dodałbym kod do pliku .xaml.cs widoku, który tworzy wystąpienie okna dialogowego i ustawia tę samą instancję ViewModel (lub coś innego, jeśli to konieczne) jako jego DataContext.
Cóż, nie musisz go używać w kilku miejscach. Oto jak bym to rozwiązał:
Myślę, że celem MVVM jest przede wszystkim oddzielenie logiki aplikacji od konkretnego UI, co pozwala na łatwe modyfikacje (lub całkowitą wymianę) UI.
Używam następującej zasady: ViewModel może wiedzieć i założyć wszystko, czego chce, z ViewModel, ale ViewModel nie może NIC wiedzieć o widoku.
WPF zapewnia ładny model powiązań, którego można użyć, aby to osiągnąć.
(Przy okazji, szablony i wyrażenia lambda nie są ezoteryczne, jeśli są prawidłowo używane. Ale jeśli nie chcesz, nie używaj ich).
Tak, znam to uczucie. Dokładnie to, co czułem, kiedy po raz pierwszy zobaczyłem MVVM. Ale kiedy już to zrozumiesz, nie będzie już źle.
Dlaczego miałbyś umieścić ViewModel za oknem na temat? Nie ma w tym sensu.
Tak, ponieważ sam fakt, że element UI znajduje się w tym samym oknie lub w innym oknie, albo że orbituje obecnie wokół Marsa, nie stanowi problemu dla ViewModels.
Rozdzielenie problemów
EDYTOWAĆ:
Oto bardzo fajny film, którego tytuł brzmi: Zbuduj swój własny framework MVVM . Warto obejrzeć.
źródło
Dla zwykłego modalnego okna dialogowego? Z pewnością robisz tam coś złego - implementacja MVVM nie musi być tak skomplikowana.
Biorąc pod uwagę, że jesteś nowy zarówno w MVVM, jak i WPF, prawdopodobnie wszędzie używasz nieoptymalnych rozwiązań i niepotrzebnie komplikujesz rzeczy - przynajmniej zrobiłem to, kiedy po raz pierwszy przeszedłem na WPF. Przed poddaniem się upewnij się, że problem dotyczy naprawdę MVVM, a nie implementacji.
MVVM, MVC, Document-View itp. To stara rodzina wzorców. Są wady, ale nie ma fatalnych usterek tego rodzaju, które opisujesz.
źródło
Jestem w trakcie dość złożonego rozwoju MVVM przy użyciu PRISM, więc już musiałem sobie radzić z tego rodzaju problemami.
Moje osobiste wnioski:
MVVM vs MVC / PopUps & co
źródło
Problem dialogów rozwiązuję oszukując. My MainWindow implementuje interfejs IWindowServices, który uwidacznia wszystkie okna dialogowe specyficzne dla aplikacji. Moje inne ViewModels mogą następnie zaimportować interfejs usług (używam MEF, ale możesz łatwo ręcznie przekazać interfejs przez konstruktory) i użyć go do wykonania tego, co jest konieczne. Na przykład, oto jak wygląda interfejs dla mojej małej aplikacji użytkowej:
//Wrapper interface for dialog functionality to allow for mocking during tests public interface IWindowServices { bool ExecuteNewProject(NewProjectViewModel model); bool ExecuteImportSymbols(ImportSymbolsViewModel model); bool ExecuteOpenDialog(OpenFileDialog dialog); bool ExecuteSaveDialog(SaveFileDialog dialog); bool ExecuteWarningConfirmation(string text, string caption); void ExitApplication(); }
To umieszcza wszystkie wykonania Dialog w jednym miejscu i można je łatwo usunąć do testów jednostkowych. Podążam za wzorcem, który klient okna dialogowego musi utworzyć odpowiedni ViewModel, który może następnie skonfigurować w razie potrzeby. Bloki wywołań Execute, a następnie klient może przejrzeć zawartość ViewModel, aby zobaczyć wyniki Dialog.
Bardziej `` czysty '' projekt MVVM może być ważny w przypadku dużych aplikacji, gdzie potrzebna jest czystsza izolacja i bardziej złożony skład, ale w przypadku małych i średnich aplikacji myślę, że praktyczne podejście, z odpowiednimi usługami do wyeksponowania wymaganych haków, jest wystarczające .
źródło
Wzorce projektowe mają Ci pomóc, a nie przeszkadzać. Niewielka część bycia dobrym programistą polega na tym, aby wiedzieć, kiedy „łamać zasady”. Jeśli MVVM jest uciążliwe dla zadania i ustaliłeś, że przyszła wartość nie jest warta wysiłku, nie używaj wzorca. Na przykład, jak skomentowały inne plakaty, dlaczego miałbyś przechodzić przez wszystkie koszty ogólne, aby wdrożyć proste pudełko na temat?
Wzorce projektowe nigdy nie miały być dogmatycznie przestrzegane.
źródło
Jak sam wzór, MVVM jest świetny. Ale biblioteka kontrolna WPF dostarczana z obsługą wiązania danych NET 4.0 jest bardzo ograniczona, jest o wiele lepsza niż WinForm, ale nadal nie jest wystarczająca dla MVVM z możliwością wiązania, powiedziałbym, że jej moc wynosi około 30% tego, co jest potrzebne do powiązania MVVM.
Bindable MVVM: to interfejs użytkownika, w którym ViewModel jest połączony z widokiem tylko przy użyciu powiązania danych.
Wzorzec MVVM dotyczy reprezentacji obiektu ViewState, nie opisuje sposobu utrzymywania synchronizacji między View i ViewModel, w WPF jest to powiązanie danych, ale może to być wszystko. I faktycznie możesz użyć wzorca MVVM w dowolnym zestawie narzędzi UI, który obsługuje zdarzenia \ wywołania zwrotne, możesz go użyć w czystym WinAPI w WinForms (tak zrobiłem i nie jest to dużo więcej pracy ze zdarzeniami \ callbackami), a możesz nawet użyć go w tekście Konsola, podobnie jak przepisywanie programu Norton Commander w DoS przy użyciu wzorca MVVM.
Krótko mówiąc: MVVM nie jest bezcelowe, jest świetne. Biblioteka formantów .NET 4.0 WPF to kosz.
Oto prosty dowód słuszności koncepcji ViewModel, którego nie można powiązać z danymi w czysty sposób MVVM przy użyciu WPF.
public class PersonsViewModel { public IList<Person> PersonList; public IList<ColumnDescription> TableColumns; public IList<Person> SelectedPersons; public Person ActivePerson; public ColumnDescription SortedColumn; }
Nie możesz powiązać danych nagłówków kolumn DataGrid WPF, nie możesz powiązać danych z wybranymi wierszami itp. Itp., Zrobisz to w prosty sposób kodem lub napiszesz 200 wierszy kodu hakerskiego XAML dla tych 5 wierszy najprostszego ViewModel. Możesz sobie tylko wyobrazić, jak sytuacja się pogarsza ze złożonymi ViewModels.
Więc odpowiedź jest prosta, chyba że piszesz aplikację Hello World, używanie wiążącego się MVVM w WPF nie ma sensu. Większość czasu spędzisz na myśleniu o hackowaniu, aby powiązać Cię z ViewModelem. Wiązanie danych jest przyjemne, ale przygotuj się na powrót do 70% czasu zdarzenia.
źródło
Nie, to nie jest bezcelowe, ale trudno jest owinąć głowę, mimo że sam wzór jest absurdalnie prosty. Istnieje mnóstwo dezinformacji i różnych grup, które walczą o właściwy sposób. Myślę, że w przypadku WPF i Silverlight powinieneś użyć MVVM albo będziesz zbytnio kodować i próbować rozwiązać problemy w nowym modelu „starej” metodologii wygrywających formularzy, która po prostu prowadzi do kłopotów. Jest to bardziej przypadek w Silverlight, ponieważ wszystko musi być asynchroniczne (możliwe są hacki wokół tego, ale powinieneś po prostu wybrać inną platformę).
Sugeruję przeczytanie tego artykułu Upraszczanie widoku drzewa WPF przy użyciu wzorca ViewModel uważnie, aby zobaczyć, jak można dobrze zaimplementować MVVM i umożliwić zmianę mentalności form wygrywających na nowy sposób myślenia w MVVM. W skrócie, jeśli chcesz coś zrobić, najpierw zastosuj logikę do ViewModel, a nie do View. Chcesz wybrać przedmiot? Zmienić ikonę? Nie iteruj po elementach interfejsu użytkownika, po prostu zaktualizuj właściwości modeli i pozwól, aby powiązanie danych załatwiło sprawę.
źródło
Widziałem ten sam problem z wieloma implementacjami MVVM, jeśli chodzi o (modalne) okna dialogowe. Kiedy patrzę na uczestników wzorca MVVM, to mam wrażenie, że czegoś brakuje do zbudowania spójnej aplikacji.
Ale brakuje:
Moje podejście polega na wprowadzeniu kontrolera (przypadku użycia), który jest odpowiedzialny za brakujące punkty. Jak to działa, można zobaczyć w przykładowych aplikacjach WPF Application Framework (WAF) .
źródło