WPF MVVM 從 ViewModel 觸發事件的正確方法
在我的 WPF 應用程序中,我有 2 個 Windows(兩個 Windows 都有自己的 ViewModel):
- 應用程序的主視窗,顯示帶有一堆單詞的列表(綁定到 MainViewModel)
- 允許使用者向列表中添加新項目的對話框視窗(綁定到 AddWordViewModel)
MainViewModel 具有 List 的 Articles 屬性(此集合由服務類之一填充)綁定到主視窗的 ListBox
AddWordViewModel 有 SaveWordCommand 綁定到添加 Word 對話框的保存按鈕。它的任務是獲取使用者輸入的文本並將其傳遞給服務類。
使用者點擊保存按鈕後,我需要通知 MainViewModel 從服務重新載入文章。
我的想法是在 MainViewModel 中公開公共命令並從 AddWordViewModel 執行它
實現它的正確方法是什麼?
謝謝!
事件聚合器是解決此類問題的好方法。基本上有一個集中的類(為了簡單起見,假設它是一個單例並且面對可能的反單例傢伙的憤怒)負責將事件從一個對象轉移到另一個對象。使用您的類名,用法可能如下所示:
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)); } }這種模式的優點是您可以非常輕鬆地擴展您的應用程序,使其具有多種創建單詞的方法和多個對已添加的單詞感興趣的 ViewModel,並且兩者之間沒有耦合,因此您可以在添加和刪除它們時添加和刪除它們。需要。
如果您想避免單例(出於測試目的,我建議您這樣做),那麼可能值得研究依賴注入,儘管這確實是另一個問題。
好吧,最後的想法。我從重新閱讀您的問題中看到,您已經擁有某種處理 Word 對象的檢索和儲存的 Word Service 類。沒有理由在添加新單詞時服務不能負責引發事件,因為兩個 ViewModel 都已經耦合到它。雖然我仍然建議 EventAggregator 更靈活和更好的解決方案,但YAGNI可能適用於這裡
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 } }您要避免做的是引入 ViewModel 之間的耦合,您將通過在一個 ViewModel 上與另一個 ViewModel 呼叫命令來創建該耦合,這將嚴重限制您擴展應用程序的選項(如果第二個 ViewModel 對新詞感興趣怎麼辦? ,現在 AddWordViewModel 也有責任告訴那個人嗎?)