W MVVM czy ViewModel lub Model powinien implementować INotifyPropertyChanged?

Większość przykładów MVVM, przez które pracowałem, miała Model zaimplementowany w INotifyPropertyChanged, ale w Przykład poleceń Josha Smitha ViewModel implementuje INotifyPropertyChanged .

Wciąż kombinuję koncepcje MVVM, więc nie wiem czy:

  • musisz umieścić INotifyPropertyChanged w ViewModel, aby uruchomić Komendy
  • to jest po prostu aberracja normy i tak naprawdę nie Materia
  • zawsze powinieneś mieć implementację modelu INotifyPropertyChanged i jest to tylko błąd, który byłby poprawiony, gdyby został opracowany z przykładu kodu do aplikacji

Jakie były doświadczenia innych w projektach MVVM, nad którymi pracowałeś?

 147
Author: Edward Tanguay, 2009-04-21

15 answers

Powiedziałbym wręcz przeciwnie, zawsze umieszczam mój INotifyPropertyChanged Na moim ViewModel - naprawdę nie chcesz zanieczyszczać swojego modelu dość specyficzną cechą WPF, taką jak INotifyPropertyChanged, to rzeczy powinny siedzieć w ViewModel.

Jestem pewien, że inni się nie zgodzą, ale tak właśnie pracuję.
 92
Author: Steven Robbins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-15 09:01:07

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 używa tego do identyfikacji zmian, ale to nie znaczy, że jest to interfejs UI. Porównałbym to do następującego komentarza: "opona jest akcesorium samochodowym ". Pewnie, że tak, ale rowery, autobusy itp. użyj go również. podsumowując, nie traktuj tego interfejsu jako interfejsu użytkownika.

Powiedziawszy to, nie koniecznie oznacza, że uważam, że Model powinien dostarczać powiadomienia. w zasadzie model nie powinien implementować tego interfejsu, chyba że jest to konieczne. w większości przypadków, gdy dane serwera nie są przesyłane do aplikacji klienckiej, model może być przestarzały. Ale jeśli słuchając danych z rynku finansowego, to nie rozumiem, dlaczego model nie może zaimplementować interfejsu. Jako przykład, co jeśli mam logikę nie-UI, taką jak usługa, która po otrzymaniu ceny Bid lub Ask za dany value it issues an alert (ex. przez e-mail) lub złożyć zamówienie? To może być możliwe czyste rozwiązanie.

Istnieją jednak różne sposoby osiągania rzeczy, ale zawsze opowiadałbym się za prostotą i unikaniem redundancji.

Co jest lepsze? Definiowanie zdarzeń w kolekcji lub zmian właściwości w modelu widoku i propagowanie go do modelu lub posiadanie widoku samoistnie aktualizować model (poprzez model widoku)?

The bottom line whenever you see ktoś twierdzi, że " nie możesz zrobić tego lub tamtego " to znak, że nie wiedzą, o czym mówią.

To naprawdę zależy od Twojego przypadku i w rzeczywistości MVVM jest frameworkiem z wieloma problemami i jeszcze nie widzę wspólnej implementacji MVVM na całym świecie.

Chciałbym mieć więcej czasu na wyjaśnienie wielu smaków MVVM i niektórych rozwiązań typowych problemów-głównie dostarczanych przez innych programistów, ale chyba będę musiał to zrobić innym razem.

 126
Author: Paulo Sousa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-28 05:53:16

W M-V-VM ViewModel zawsze (Model nie zawsze) implementuje INotifyPropertyChanged

Zobacz szablon projektu M-V-VM / Zestaw Narzędzi Z http://blogs.msdn.com/llobo/archive/2009/05/01/download-m-v-vm-project-template-toolkit.aspx. Używa DelegateCommand do dowodzenia i powinien być świetnym szablonem startowym dla projektów M-V-VM.

 27
Author: Soni Ali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-26 18:45:34

Myślę, że MVVM jest bardzo źle nazwany i nazywanie ViewModel ViewModel powoduje, że wielu pomija ważną cechę dobrze zaprojektowanej architektury, jaką jest Kontroler danych, który kontroluje dane bez względu na to, kto próbuje je dotknąć.

Jeśli pomyślisz o modelu widoku jako o Datacontrolle i zaimplementujesz architekturę, w której Twój DataController jest jedyną pozycją, która dotyka danych, to nigdy nie dotkniesz danych bezpośrednio, ale zawsze używasz Datacontrollera. Na DataController jest przydatny dla interfejsu użytkownika, ale niekoniecznie tylko dla interfejsu użytkownika. Jest to warstwa biznesowa, warstwa interfejsu użytkownika itp...

DataModel -------- DataController ------ View
                  /
Business --------/
Kończysz z takim modelem. Nawet firma powinna dotykać danych tylko za pomocą modelu widoku. Wtedy twoja zagadka po prostu zniknie.
 9
Author: Rhyous,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-11 22:43:56

To zależy od tego, jak zaimplementowałeś swój model. Moja firma wykorzystuje obiekty biznesowe podobne do obiektów CSLA Lhotki i szeroko wykorzystuje INotifyPropertyChanged w całym modelu biznesowym.

Nasz silnik walidacji opiera się w dużej mierze na informowaniu, że właściwości zmieniają się dzięki temu mechanizmowi i działa bardzo dobrze. Oczywiście, jeśli używasz innej implementacji innej niż business objects, w której Powiadamianie o zmianach nie ma tak krytycznego znaczenia dla operacji, możesz posiadaj inne metody wykrywania zmian w modelu biznesowym.

Mamy również modele widoku, które propagują zmiany z modelu w razie potrzeby, ale same modele widoku słuchają podstawowych zmian modelu.

 7
Author: Steve Mitcham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-21 12:55:52

Myślę, że odpowiedź jest dość jasna, jeśli chcesz trzymać się MV-VM.

Zobacz: http://msdn.microsoft.com/en-us/library/gg405484 (v=PandP.40).aspx

We wzorze MVVM widok hermetyzuje interfejs użytkownika i dowolną logikę interfejsu użytkownika, model widoku hermetyzuje logikę prezentacji i stan, a model hermetyzuje logikę biznesową i dane.

" widok współdziała z modelem widoku poprzez powiązanie danych, polecenia i zdarzenia powiadomień o zmianie. Zapytania modelu widoku, obserwuje i koordynuje aktualizacje modelu, konwertuje, waliduje i agreguje dane w razie potrzeby do wyświetlenia w widoku. "

 3
Author: John D,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-24 06:46:42

Powiedziałbym, że Twoim zdaniem. Nie jest częścią modelu, ponieważ Model jest agnostyczny. Model powinien być "wszystko poza agnostykiem biznesowym"

 2
Author: Steve Dunn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-21 12:48:55

Ale czasami (jak w tej prezentacji link text) model jest usługą, która dostarcza aplikacji pewne dane online, a następnie trzeba emplement powiadomienia, że nowe dane przybyły lub dane zmieniły się za pomocą zdarzeń...

 2
Author: Andrey Khataev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-10 14:07:02

Myślę, że wszystko zależy od przypadku użycia.

Gdy 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 mieszka w interaktywnej domenie modelowej-modele odwołujące się do modeli, subskrybowanie zdarzeń innych modeli - posiadanie zdarzeń modelowych zaimplementowanych jako INPC to koszmar.

Postaw się w pozycji jakiegoś modelowego bytu, który musi współpracować z innymi modelami. Masz różne wydarzenia do subskrypcji. Wszystkie z nich są zaimplementowane jako INPC. Wyobraź sobie, że masz obsługę zdarzeń. Jedna ogromna kaskada if-clauses i / lub switch clauses.

Kolejny problem z INPC. Powinieneś projektować swoje aplikacje w oparciu o abstrakcję, a nie implementację. Zazwyczaj odbywa się to za pomocą interfejsów.

Spójrzmy na 2 różne implementacje tej samej abstrakcji:

public class ConnectionStateChangedEventArgs : EventArgs
{
    public bool IsConnected {get;set;}
}

interface IConnectionManagerINPC : INotifyPropertyChanged
{
    string Name {get;}
    int ConnectionsLimit {get;}
    /*

    A few more properties

    */
    bool IsConnected {get;}
}

interface IConnectionManager
{
    string Name {get;}
    int ConnectionsLimit {get;}
    /*

    A few more properties

    */
    event EventHandler<ConnectionStateChangedEventArgs> ConnectionStateChanged;
    bool IsConnected {get;}
}
Spójrz teraz na obie. Co robi IConnectionManagerINPC ci powiedział? Że niektóre jego właściwości mogą ulec zmianie. Nie wiesz, który z nich. W rzeczywistości projekt polega na tym, że tylko IsConnected zmienia się, ponieważ reszta z nich jest tylko do odczytu.

Przeciwnie, intencje IConnectionManager są jasne: "mogę ci powiedzieć, że wartość mojej właściwości IsConnected może ulec zmianie".

 1
Author: dzendras,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-19 13:12:28

Po prostu użyj INotifyPropertyChange w swoim viewmodelu, a nie w modelu,

Model zazwyczaj używa IDataErrorInfo do obsługi błędów walidacji, więc po prostu trzymaj się swojego ViewModel i jesteś na swojej drodze MVVM.

 1
Author: Adam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-15 09:02:38

Zgadzam się z odpowiedzią Paulo, implementacja INotifyPropertyChanged w modelach jest całkowicie akceptowalna i jest nawet sugerowana przez Microsoft -

Zazwyczaj model wdraża udogodnienia, które ułatwiają / align = "left" / Zazwyczaj oznacza to, że obsługuje właściwości i zgłoszenie zmiany kolekcji poprzez INotifyPropertyChanged i INotifyCollectionChanged interfejsy. Klasy modeli, które reprezentują zbiory obiektów zazwyczaj wywodzą się z ObservableCollection<T> klasa, która zapewnia implementację INotifyCollectionChanged interfejs.

Chociaż to do ciebie, aby zdecydować, czy chcesz tego typu implementacji, czy nie, ale pamiętaj -

Co zrobić, jeśli Twoje klasy modelowe nie implementują wymaganych interfejsów?

Czasami trzeba będzie pracować z obiektami modelu, które nie zaimplementuj INotifyPropertyChanged, INotifyCollectionChanged, IDataErrorInfo, lub INotifyDataErrorInfo interfejsy. W takich przypadkach, model widoku może wymagać zawinięcia obiektów modelu i odsłonięcia wymagane właściwości do widoku. Na wartości dla tych właściwości będą być dostarczane bezpośrednio przez obiekty modelu. Model widoku będzie zaimplementować wymagane interfejsy dla właściwości, które wystawia tak że Widok może łatwo powiązać z nimi dane.

Wzięte z - http://msdn.microsoft.com/en-us/library/gg405484 (PandP. 40). aspx

Pracowałem w kilku projektach, w których nie zaimplementowaliśmy INotifyPropertyChanged w naszych modelach i z tego powodu napotkaliśmy wiele problemów; niepotrzebne powielanie właściwości było potrzebne w VM i jednocześnie musieliśmy zaktualizować obiekt bazowy (z zaktualizowanymi wartościami) przed przekazaniem ich do BL/DL.

Problemy pojawią się szczególnie wtedy, gdy będziesz musiał pracować z kolekcją obiektów modelu (np. w edytowalnej siatce lub liście) lub złożonych modeli; obiekty modelu nie będą aktualizowane automatycznie i będziesz musiał zarządzać tym wszystkim w maszynie wirtualnej.


Pierwotnie odpowiedział na inne podobne pytanie, dodając tutaj, ponieważ zawiera imp. brakuje szczegółów z ten wątek -

Https://stackoverflow.com/a/6923833/45382

 1
Author: akjoshi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:10

Załóżmy, że odniesienie do obiektu w Twoim widoku ulegnie zmianie. W jaki sposób powiadomisz wszystkie właściwości, które mają być aktualizowane, aby pokazać prawidłowe wartości? Wywołanie OnPropertyChanged w Twoim widoku dla wszystkich właściwości obiektu jest śmieciem z mojego punktu widzenia.

Więc to, co robię, to pozwolić, aby sam obiekt powiadamiał kogokolwiek, gdy wartość w Właściwości się zmienia, a moim zdaniem używam wiązań takich jak Object.Property1, Object.Property2 i dalej. W ten sposób, jeśli tylko Chcę zmienić obiekt, który jest obecnie utrzymywany w moim odczuciu, po prostu do OnPropertyChanged("Object").

Aby uniknąć setek powiadomień podczas ładowania obiektów, mam prywatny wskaźnik boolean, który ustawiłem na true podczas ładowania, który jest sprawdzany z obiektu OnPropertyChanged i nic nie robi.

 0
Author: Dummy01,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-23 07:15:45

Używam interfejsu INotifyPropertyChange w modelu. W rzeczywistości zmiana właściwości modelu powinna być wywołana tylko przez interfejs użytkownika lub klienta zewnętrznego.

Zauważyłem kilka zalet i wad:

Zalety

Zgłaszający jest w modelu biznesowym

  1. Jak na domenę napędzane, To jest prawo. Powinien zdecydować, kiedy podnieść, a kiedy nie.

Wady

Model ma właściwości (ilość, stawka, prowizja, suma). Totalfrieght jest obliczany na podstawie ilości, stawki, zmiany prowizji.

  1. Przy ładowaniu wartości z db, całkowite obliczenie frieght jest wywoływane 3 razy (ilość, stawka, prowizja). Powinien być raz.

  2. Jeśli stawka, ilość jest przypisana w warstwie biznesowej, ponownie wywoływany jest notifier.

  3. Powinna istnieć opcja, aby to wyłączyć, prawdopodobnie w klasie bazowej. Jednak deweloperzy mogli zapomnieć o tym.

 0
Author: Anand Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-21 14:33:21

Normalnie ViewModel zaimplementuje INotifyPropertyChanged. Model może być dowolny(plik xml, baza danych, a nawet obiekt). Model jest używany do przekazywania danych do modelu widoku, który propaguje się do widoku.

Zobacz tutaj

 0
Author: Syed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-15 09:02:54

Imho myślę, że ViewModel implementuje {[0] } i model mógłby używać powiadomień na innym "poziomie".

Eg w przypadku niektórych usług dokumentu i obiektu dokumentu występuje zdarzenie documentChanged, którego słucha model widoku, aby wyczyścić i odbudować widok. W modelu edytuj Widok masz właściwośćzmienić Właściwości dokumentu w celu obsługi widoków. Jeśli usługa robi dużo z dokumentem przy zapisie (aktualizacja daty zmiany, ostatniego użytkownika i tak dalej), łatwo można uzyskać przeciążenie z ipropertychanged zdarzeń i wystarczy dokumentchanged.

Ale jeśli używasz INotifyPropertyChange w swoim modelu myślę, że dobrą praktyką jest przekazywanie go w Twoim viewmodel zamiast subskrybować go bezpośrednio w Twoim ViewModel. W takim przypadku, gdy zdarzenia zmieniają się w twoim modelu, musisz tylko zmienić model widoku i widok pozostaje nietknięty.

 0
Author: Bram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-26 04:35:21