2010-11-17 20 views
6

Zajmuję się tworzeniem aplikacji WPF przy użyciu wzorca MVVM. Używam biblioteki MVVM Light i próbuję również użyć wtryskiwacza zależności (rozważam Ninject i Unity).MVVM: Komunikacja między modelem i ViewModels

Przeczytałem wiele artykułów na blogu i jestem bardzo zdezorientowany "prawidłowym" sposobem komunikowania się moich klas ze sobą. W szczególności nie wiem, kiedy stosować Dependency Injection i kiedy polegać na wzorcu mediatora.

Rozważmy przykład. Mam ViewModel, nazwijmy to DataViewModel i klasę danych, która dostarcza pewnego rodzaju danych. Jak lepiej się między nimi komunikować:

A. Wprowadzić zależność do DataViewModel z interfejsem IData? W ten sposób dane nie będą musiały polegać na Messengerze, ale będą musiały dostarczyć zdarzenie, jeśli dane się zmienią, a ViewModel będzie musiał je zasubskrybować.

B. Polegać na wzorcu mediatora (zaimplementowanym w MVVM Light jako Messenger) i wysłać wiadomości między Modelem a ViewModel? W ten sposób nie będzie konieczne stosowanie Dependency Injection, ponieważ cała komunikacja będzie oparta na wiadomościach.

Co więcej, czy moje ViewModels wstrzyknęłyby zależności innym ViewModels, czy lepiej byłoby polegać na komunikatorze? Jeśli pierwszy, czy konieczne byłoby zdefiniowanie osobnego interfejsu dla każdego ViewModel? Myślę, że zdefiniowanie interfejsu dla każdej maszyny wirtualnej będzie dodatkową pracą, ale może warto.

Odpowiedz

4

Ogólnie ViewModel przechodzi do usługi (jak pryzmat ją wywołuje) w celu pobrania potrzebnych danych. Ta usługa jest przekazywana do ViewModel przez DI (Constructor Injection), chociaż można to wykonać w inny sposób za pośrednictwem ServiceLocator.

Dlatego Twój ViewModel będzie zawierał odnośnik do usługi, która odciąży pobieranie Twoich danych. Dane mogą pochodzić z DB, pliku XML, który wie ... abstrakcja tam jest. Tak więc dla twojego przypadku IData, odniesienie do tego typu pojawi się w pewnym momencie w ViewModel, ale nie przez żadnego z DI. Jeśli pozwala na to twoja struktura IoC (Prism robi), tworzysz odwzorowania typów interfejsów na konkretne typy, a następnie pobierasz te typy poprzez swój kontener; tak jest w przypadku Unity.

Oto krótki przykład ... Skrypty są powiązane z widokiem, a ViewModel jest wstrzykiwany do widoku. Zwróć uwagę na użycie IScriptService do pobrania danych. Dane wracają to zbiór typów IScript, jednak nigdy formalnie nie wstrzykiwaliśmy tego typu do ViewModel, ponieważ nie dbamy o typ jako pojedynczy obiekt, którym zależy na typie w skali wielkości.

 public ScriptRepositoryViewModel(IUnityContainer container, IScriptService scriptService, IEventAggregator eventAggregator) 
     { 
      _container = container; 
      _scriptService = scriptService; 
      _eventAggregator = eventAggregator; 
     } 

     public ICollectionView Scripts 
     { 
      get 
      { 
       if (_view == null) 
       { 
        _view = CollectionViewSource.GetDefaultView(_scriptService.Scripts); 
        _view.Filter = Filter; 
       } 

       return _view; 
      } 
     } 

Kiedy sobie drogę do widzenia, sama obudowa może być nie miał, widok będzie się wstrzykiwany poprzez di (Konstruktor Injection) z ViewModel. Nie uzależniałbym innych modeli ViewModels od siebie, trzymam je w izolacji. Jeśli zaczniesz dostrzegać potrzebę sprzężenia, spójrz na dane, które próbujesz udostępnić, tym częściej dane te muszą zostać wyodrębnione i nie powinny być sprzężone z żadnym modelem ViewModel.

+0

Teraz rozumiem ... ale potrzebowałem trochę czasu, aby przyzwyczaić się do zastrzyku zależności i usług :) Dzięki! – madbadger

1

Jest więcej niż jeden dobrym rozwiązaniem problemu,

Proponuję użyć jakiegoś jednego interfejsu w swoich modelach danych, umieścić go w klasie bazowej, interfejs ten pozwoli obiektami danych do komunikowania się z świat zewnętrzny.

Dla modeli widoku nie wstrzykuje danych, ale interfejs, który może pobrać dane dla ciebie, dane będą wystawiać zdarzenia, które vm może zarejestrować się do nich po ich otrzymaniu.

Dane oject nie powinny wiedzieć, kto go trzyma, model widoku wie, jakie dane posiada, ale nie zalecam wprowadzania tych danych ze względu na problemy z elastycznością.

Powiązane problemy