Większość przykładów MVVM, przez które pracowałem, miało implementację ModelINotifyPropertyChanged
, ale w przykładzie CommandSink Josha Smitha implementuje ViewModelINotifyPropertyChanged
.
Nadal poznawczo łączę koncepcje MVVM, więc nie wiem, czy:
INotifyPropertyChanged
Aby zabrać sięCommandSink
do pracy, musisz wstawić ViewModel- To tylko aberracja normy i nie ma to większego znaczenia
- Zawsze powinieneś mieć implementację Model
INotifyPropertyChanged
i jest to tylko błąd, który zostałby poprawiony, gdyby został opracowany z przykładu kodu do aplikacji
Jakie były doświadczenia innych z projektami MVVM, nad którymi pracowałeś?
c#
mvvm
inotifypropertychanged
Edward Tanguay
źródło
źródło
Odpowiedzi:
Powiedziałbym wręcz przeciwnie, zawsze umieszczam mój
INotifyPropertyChanged
na moim ViewModel - naprawdę nie chcesz zanieczyszczać swojego modelu funkcją dość specyficzną dla WPF, na przykładINotifyPropertyChanged
te rzeczy powinny znajdować się w ViewModel.Jestem pewien, że inni by się nie zgodzili, ale tak właśnie pracuję.
źródło
Zdecydowanie nie zgadzam się z koncepcją, że Model nie powinien implementować
INotifyPropertyChanged
. Ten interfejs nie jest specyficzny dla interfejsu użytkownika! Po prostu informuje o zmianie. Rzeczywiście, WPF intensywnie wykorzystuje to do identyfikowania zmian, ale to nie znaczy, że jest to interfejs interfejsu użytkownika. Porównałbym to do komentarza: „ Opona to akcesorium samochodowe ”. Jasne, ale korzystają z niego także rowery, autobusy itp. Podsumowując, nie traktuj tego interfejsu jako elementu interfejsu użytkownika.Powiedziawszy to, niekoniecznie oznacza to, że uważam, że Model powinien dostarczać powiadomienia. W rzeczywistości model nie powinien implementować tego interfejsu, chyba że jest to konieczne. W większości przypadków, gdy żadne dane serwera nie są przekazywane do aplikacji klienckiej, model może być nieaktualny. Ale słuchając danych z rynków finansowych, to nie widzę, dlaczego model nie może zaimplementować interfejsu. Na przykład, co zrobić, jeśli mam logikę inną niż UI, taką jak usługa, która po otrzymaniu ceny kupna lub sprzedaży dla danej wartości generuje alert (np. Za pośrednictwem wiadomości e-mail) lub składa zamówienie? Może to być możliwe czyste rozwiązanie.
Istnieją jednak różne sposoby osiągnięcia pewnych rzeczy, ale zawsze opowiadałbym się za prostotą i unikaniem nadmiarowości.
Co jest lepsze? Definiowanie zdarzeń w kolekcji lub zmian właściwości w modelu widoku i propagowanie ich do modelu lub sprawienie, aby widok wewnętrznie aktualizował model (za pośrednictwem modelu widoku)?
Podsumowując, ilekroć zobaczysz kogoś, kto twierdzi, że „ nie możesz zrobić tego lub tamtego ”, jest to znak, że nie wie, o czym mówi.
To naprawdę zależy od twojego przypadku i tak naprawdę MVVM to framework z wieloma problemami i nie widzę jeszcze wspólnej implementacji MVVM we wszystkich dziedzinach.
Chciałbym mieć więcej czasu na wyjaśnienie wielu odmian MVVM i kilku rozwiązań typowych problemów - w większości dostarczonych przez innych programistów, ale myślę, że będę musiał to zrobić innym razem.
źródło
INotifyPropertyChanged
jest częściąSystem.ComponentModel
przestrzeni nazw, która służy do „ zachowania komponentów i formantów w czasie wykonywania i projektowania w czasie projektowania ”. NIE UŻYWAJINotifyPropertyChanged
w modelach, tylko w ViewModels. Łącze do dokumentów: docs.microsoft.com/en-us/dotnet/api/system.componentmodelW MV-VM ViewModel zawsze (Model nie zawsze) implementuje
INotifyPropertyChanged
Zapoznaj się z szablonem projektu / zestawem narzędzi MV-VM na stronie http://blogs.msdn.com/llobo/archive/2009/05/01/download-mv-vm-project-template-toolkit.aspx . Używa
DelegateCommand
do dowodzenia i powinien być świetnym szablonem początkowym dla projektów MV-VM.źródło
Myślę, że MVVM jest bardzo słabo nazwane i wywołanie ViewModel a ViewModel powoduje, że wielu pomija ważną cechę dobrze zaprojektowanej architektury, którą jest DataController, który kontroluje dane bez względu na to, kto próbuje ich dotknąć.
Jeśli myślisz o modelu widoku jako bardziej o kontrolerze danych i zaimplementujesz architekturę, w której kontroler danych jest jedynym elementem, który dotyka danych, nigdy nie dotykasz danych bezpośrednio, ale zawsze używasz DataController. DataController jest przydatny dla interfejsu użytkownika, ale niekoniecznie tylko dla interfejsu użytkownika. To jest dla warstwy biznesowej, warstwy interfejsu użytkownika itp ...
Skończysz z takim modelem. Nawet firma powinna dotykać danych tylko za pomocą ViewModel. Wtedy twoja zagadka po prostu znika.
źródło
To zależy od tego, jak zaimplementowałeś swój model. Moja firma używa obiektów biznesowych podobnych do obiektów CSLA firmy Lhotka i szeroko korzysta z nich
INotifyPropertyChanged
całym modelu biznesowym.Nasz silnik walidacji w dużej mierze polega na otrzymywaniu powiadomienia, że właściwości zmieniają się za pośrednictwem tego mechanizmu i działa on bardzo dobrze. Oczywiście, jeśli używasz innej implementacji niż obiekty biznesowe, gdzie powiadamianie o zmianach nie jest tak krytyczne dla operacji, możesz mieć inne metody wykrywania zmian w modelu biznesowym.
Mamy również modele widoku, które w razie potrzeby propagują zmiany z modelu, ale same modele widoku nasłuchują podstawowych zmian modelu.
źródło
Zgadzam się z odpowiedzią Paulo, implementacja
INotifyPropertyChanged
w modelach jest całkowicie akceptowalna, a nawet sugerowana przez Microsoft -Chociaż to od Ciebie zależy, czy chcesz tego typu implementacji, czy nie, ale pamiętaj -
Pochodzą z - http://msdn.microsoft.com/en-us/library/gg405484(PandP.40).aspx
Pracowałem przy kilku projektach, w których nie wdrożyliśmy ich
INotifyPropertyChanged
w naszych modelach i przez to napotkaliśmy wiele problemów; konieczne było niepotrzebne powielanie właściwości w VM i jednocześnie musieliśmy aktualizować bazowy obiekt (zaktualizowanymi wartościami) przed przekazaniem ich do BL / DL.Napotkasz problemy szczególnie, jeśli będziesz musiał pracować z kolekcją obiektów swojego modelu (powiedzmy na edytowalnej siatce lub liście) lub złożonymi modelami; obiekty modelu nie będą aktualizowane automatycznie i będziesz musiał zarządzać tym wszystkim na swojej maszynie wirtualnej.
źródło
Ale czasami (jak w tym tekście linku do prezentacji ) model to usługa, która dostarcza aplikacji część danych w trybie online, a następnie trzeba wprowadzić powiadomienie o pojawieniu się nowych danych lub zmianie danych za pomocą zdarzeń ...
źródło
Myślę, że odpowiedź jest dość jasna, jeśli chcesz stosować się do MV-VM.
patrz: http://msdn.microsoft.com/en-us/library/gg405484(v=PandP.40).aspx
We wzorcu MVVM widok hermetyzuje interfejs użytkownika i dowolną logikę interfejsu użytkownika, model widoku hermetyzuje logikę i stan prezentacji, a model hermetyzuje logikę biznesową i dane.
źródło
Powiedziałbym w twoim ViewModel. Nie jest częścią modelu, ponieważ jest on niezależny od interfejsu użytkownika. Model powinien być „wszystkim poza biznesem agnostykiem”
źródło
Implementacja INPC w modelach może być stosowana, jeśli modele są wyraźnie widoczne w ViewModel. Ale ogólnie rzecz biorąc, ViewModel zawija modele to jego własne klasy, aby zmniejszyć złożoność modelu (co nie powinno być przydatne w przypadku wiązania). W takim przypadku INPC należy zaimplementować w ViewModel.
źródło
Używam
INotifyPropertyChange
interfejsu w modelu. W rzeczywistości zmiana właściwości modelu powinna być uruchamiana tylko przez interfejs użytkownika lub klienta zewnętrznego.Zauważyłem kilka zalet i wad:
Zalety
Zgłaszający działa w modelu biznesowym
Niedogodności
Model ma właściwości (ilość, stawka, prowizja, suma kosztów). Całkowita cena jest obliczana na podstawie ilości, stawki, zmiany prowizji.
Przy ładowaniu wartości z db, obliczenie całkowitego frieght jest wywoływane 3 razy (ilość, stawka, prowizja). Powinien być raz.
Jeśli stopa, ilość jest przypisana w warstwie biznesowej, ponownie wywoływany jest notifier.
Powinna istnieć opcja wyłączenia tego, prawdopodobnie w klasie bazowej. Jednak programiści mogli o tym zapomnieć.
źródło
Myślę, że wszystko zależy od przypadku użycia.
Kiedy masz prosty model z mnóstwem właściwości, możesz go zaimplementować w INPC. Mówiąc prościej, mam na myśli, że ten model wygląda raczej jak POCO .
Jeśli Twój model jest bardziej złożony i żyje w domenie modelu interaktywnego - modele odwołujące się do modeli, subskrybujące zdarzenia innych modeli - posiadanie zdarzeń modelowych zaimplementowanych jako INPC jest koszmarem.
Postaw się w pozycji jakiejś modelowej istoty, która musi współpracować z innymi modelami. Masz różne wydarzenia do zasubskrybowania. Wszystkie z nich są zaimplementowane jako INPC. Wyobraź sobie te programy obsługi zdarzeń, które masz. Jedna ogromna kaskada klauzul if i / lub klauzul przełączających.
Kolejny problem z INPC. Powinieneś projektować swoje aplikacje tak, aby opierały się na abstrakcji, a nie implementacji. Odbywa się to zwykle za pomocą interfejsów.
Rzućmy okiem na 2 różne implementacje tej samej abstrakcji:
Teraz spójrz na nich obu. Co mówi IConnectionManagerINPC? Że niektóre jego właściwości mogą się zmienić. Nie wiesz, który z nich. W rzeczywistości projekt jest taki, że zmienia się tylko IsConnected, ponieważ reszta z nich jest tylko do odczytu.
Z drugiej strony, intencje IConnectionManager są jasne: „Mogę powiedzieć, że wartość mojej właściwości IsConnected może się zmienić”.
źródło
Po prostu użyj
INotifyPropertyChange
w swoim modelu widoku, a nie w modelu,model zwykle używa
IDataErrorInfo
do obsługi błędów walidacji, więc po prostu pozostań w swoim ViewModel i jesteś na dobrej drodze do MVVM.źródło
Załóżmy, że odniesienie do obiektu w Twoim widoku ulegnie zmianie. W jaki sposób powiadomisz wszystkie właściwości o konieczności aktualizacji, aby wyświetlały prawidłowe wartości? Z
OnPropertyChanged
mojego punktu widzenia odwoływanie się do wszystkich właściwości obiektu jest bzdurą.Więc co mogę zrobić, to niech sam obiekt do powiadamiania kogokolwiek, gdy wartość nieruchomości ulegnie zmianie, a moim zdaniem jak używam powiązań
Object.Property1
,Object.Property2
i tak dalej. W ten sposób, jeśli chcę tylko zmienić obiekt, który jest aktualnie obsługiwany w moim widoku, po prostu robięOnPropertyChanged("Object")
.Aby uniknąć setek powiadomień podczas ładowania obiektów, mam prywatny wskaźnik boolowski, który ustawiam na true podczas ładowania, który jest sprawdzany z obiektu
OnPropertyChanged
i nic nie robi.źródło
Zwykle ViewModel zaimplementuje
INotifyPropertyChanged
. Model może być cokolwiek (plik xml, baza danych lub nawet obiekt). Model służy do przekazywania danych do modelu widoku, który jest propagowany do widoku.Spójrz tutaj
źródło
imho myślę, że Viewmodel implementuje
INotifyPropertyChange
i model mógłby używać powiadomienia na innym „poziomie”.np. w przypadku niektórych usług dokumentacyjnych i obiektu dokumentu masz zdarzenie documentChanged, którego słucha viewmodel, aby wyczyścić i odbudować widok. W modelu widoku edycji masz odpowiednią zmianę właściwości dokumentu w celu obsługi widoków. Jeśli usługa dużo robi z dokumentem przy zapisywaniu (aktualizacja daty zmiany, ostatniego użytkownika itd.), Łatwo dostajesz przeładowanie Ipropertozmienionych zdarzeń i wystarczy zmienić dokument.
Ale jeśli używasz
INotifyPropertyChange
w swoim modelu, myślę, że dobrą praktyką jest przekazywanie go w swoim modelu widoku zamiast subskrybowania go bezpośrednio w swoim widoku. W takim przypadku, gdy zdarzenia zmieniają się w modelu, wystarczy zmienić model widoku, a widok pozostaje nietknięty.źródło
Wszystkie właściwości, które są powiązane z moim widokiem, znajdują się w moich ViewModel (ach). Dlatego powinny zaimplementować interfejs INotifyPropertyChanged. Dlatego Widok otrzymuje wszystkie zmiany.
[Korzystając z zestawu narzędzi MVVM Light, pozwoliłem im dziedziczyć z ViewModelBase.]
Model zawiera logikę biznesową, ale nie ma nic wspólnego z widokiem. Dlatego nie ma potrzeby stosowania interfejsu INotifyPropertyChanged.
źródło