2009-04-28 10 views
20

W mojej aplikacji WPF mam 2 Windows (zarówno w systemie Windows mają własne ViewModel):WPF MVVM Correct sposób na ogień zdarzenia na widoku z ViewModel

  1. aplikacji Okno główne, który wyświetla listę z bukietem słów (granica do MainViewModel)

  2. Okno dialogowe, które umożliwia użytkownikom dodawanie nowych elementów do listy (związany AddWordViewModel)

MainViewModel ma Artykuły własność Li st (ta kolekcja jest zapełniana przez jedną z klas usług) związana z ListBox Listą Główną

AddWordViewModel ma SaveWordCommand, która jest przypisana do przycisku Save Word Dialog Save. Jego zadaniem jest pobranie tekstu wprowadzonego przez użytkownika i przekazanie go do klasy serwisowej.

Po kliknięciu przycisku Zapisz użytkownik muszę powiadomić MainViewModel, aby ponownie załadować artykuły z usługi.

Moim pomysłem było wystawiać polecenia publicznego w MainViewModel i wykonać go od AddWordViewModel

Jaki jest prawidłowy sposób jego realizacji?

Dziękujemy!

Odpowiedz

18

Event Aggregators to całkiem niezły sposób na rozwiązanie tego typu problemów. Zasadniczo istnieje scentralizowana klasa (dla uproszczenia, powiedzmy, że to Singleton i staw czoła możliwemu gniewowi facetów anty-singleton), która jest odpowiedzialna za przenoszenie zdarzeń z jednego obiektu do drugiego. Ze swoimi nazwami klas użycie może wyglądać następująco:

public class MainViewModel 
{ 
    public MainViewModel() 
    { 
     WordAddedEvent event = EventAggregator.Instance.GetEvent<WordAddedEvent>(); 
     event.Subscribe(WordAdded); 
    } 

    protected virtual void WordAdded(object sender WordAddedEventArgs e) 
    { 
     // handle event 
    } 
} 

public class AddWordViewModel 
{  
    //From the command 
    public void ExecuteAddWord(string word) 
    { 
     WordAddedEvent event = EventAggregator.Instance.GetEvent<WordAddedEvent>(); 
     event.Publish(this, new WordAddedEventArgs(word)); 
    } 
} 

Zaletą tego układu jest to, że można bardzo łatwo rozszerzyć swoją aplikację mieć wiele sposobów tworzenia słów i wielu ViewModels, które są zainteresowane w słowach, które zostały dodane i nie ma połączenia między nimi, więc możesz je dodawać i usuwać, jak potrzebujesz.


Jeśli chcesz uniknąć pojedyncza (i dla celów testowych I sugerowałaby to zrobić), to może warto patrząc do wstrzykiwania zależności, mimo że tak naprawdę to zupełnie inna kwestia.


Okay, ostatnia myśl. Widzę po ponownym przeczytaniu twojego pytania, że ​​masz już jakąś klasę Word Service, która obsługuje pobieranie i przechowywanie obiektów Word. Nie ma powodu, że usługa nie może być odpowiedzialna za podniesienie zdarzenia po dodaniu nowego słowa, ponieważ oba modele ViewModels są już z nim powiązane. Chociaż ja nadal sugerują EventAggregator jest bardziej elastyczny i lepszym rozwiązaniem, ale YAGNI mogą ubiegać się o

public class WordService 
{ 
    public event EventHandler<WordAddedEventArgs> WordAdded; 

    public List<string> GetAllWords() 
    { 
     //return words 
    } 

    public void SaveWord(string word) 
    { 
     //Save word 
     if (WordAdded != null) WordAdded(this, new WordAddedEventArgs(word)); 
     //Note that this way you lose the reference to where the word really came from 
     //probably doesn't matter, but might 
    } 
} 

public class MainViewModel 
{ 
    public MainViewModel() 
    { 
     //Add eventhandler to the services WordAdded event 
    } 
} 

Co chcesz uniknąć robi choć wprowadza sprzężenie pomiędzy ViewModels że będziesz tworzyć poprzez wywołanie polecenia na jednym ViewModelu z innym, to poważnie ograniczy twoje możliwości rozszerzenia aplikacji (co jeśli drugi ViewModel zainteresował się nowymi słowami, czy to teraz AddWordViewModel ma obowiązek także o tym powiedzieć?)

+0

Dziękuję za bardzo szczegółowy odpowiedź. Będę musiał się w to zagłapać :) Dużo zabawy nadchodzi :) –

+0

Poszedłem na pełne OO z ogromnym wykresem obiektów dla mojej implementacji MVVM.2 lata później i dokonanie zmian strukturalnych jest dość trudne. Żałuję, że nie poszedłem do wzorca agregator/mediator, ponieważ elastyczność jest olbrzymia. UWAGA: Wycieki pamięci. Upewnij się, że agregator używa słabych odniesień. – Gusdor

Powiązane problemy