2011-04-20 198 views
7

我有兩個ViewModels一個連接到主窗口,另一個連接到通過單擊主窗口上的按鈕打開的子窗口。子窗口包含項目列表,我想要選擇一個項目並通過更新主窗口viewmodel將其顯示在主窗口中。什麼是完成這個最好的方法。謝謝!從另一個視圖模型更新視圖模型

+1

你特別要求「最好」的方式來做到這一點。什麼定義「最好」給你?它可能意味着最快,最簡單,最容易理解/調試,最少代碼等。 – 2011-04-20 15:38:13

+0

最簡單的是非常主觀的,但我傾向於基於它的對象之間的真實關係的概念模型。如果他們是父母/孩子,直接引用可能非常簡單。 – 2011-04-20 15:39:12

+1

在這種情況下,對我來說「最好」意味着最簡單的方法,因爲我對wpf和mvvm很陌生。 – codeBlue 2011-04-20 16:02:49

回答

10

有任何數量的方式來做到這一點。

  • 將對父視圖模型的引用傳遞給子視圖並讓子視圖調用主視圖模型。

  • 讓子視圖模型觸發父訂閱的事件。

  • 使用messenger/mediator在兩者之間進行通信。父母訂閱,孩子發佈消息。這提供了鬆耦合。

  • 將主視圖模型設置爲全局服務。以某種方式註冊它。讓孩子查找服務(需要全局服務是一個很常見的問題),然後在全局/通用界面上調用一些東西。

從我的經驗來看,最簡單的方法是#2。在子視圖模型上定義一個事件。家長將不得不查看孩子(我不知道它是否包含它或您的視圖模型的構建方式)並訂閱該活動。

+0

任何這些方法都可能是合適的。這取決於上下文。除非虛擬機在緊密和概念上相關,否則耦合並不合適。 – 2011-04-20 15:30:52

+0

非常非常有用的答案,我的MainViewModel類開始看起來像一團糟。謝謝 – 2013-04-12 13:43:04

7

ViewModels之間進行通信的標準方式是使用某種類型的消息傳遞。一個很好的實施,這是MVVM Light Toolkit

下面是使用默認的信使一些(隨機)從中代碼:

//Registering: 
Messenger.Default.Register<IEnumerable<BookViewModel>>(this, true, fillSourceWith); 
Messenger.Default.Register<DisplayModeEnum>(this, ChangeMainTemplates); 
//with a specific "token" 
Messenger.Default.Register<object>(this, MessageTokens.ClearList, o => BookSource.Clear()); 

//Sending 
Messenger.Default.Send<List<BookViewModel>>(newBooks); 
Messenger.Default.Send<DisplayModeEnum>(DisplayModeEnum.MediumLayout); 
Messenger.Default.Send<object>(null, MessageTokens.ClearList); 
+0

-1。他在談論父母/孩子的關係。消息在這裏不是個好主意。 – Euphoric 2011-04-20 15:31:22

+2

我認爲這裏的消息應該沒問題。沒有消息,你不得不以某種方式將你的視圖模型結合起來。 – 2011-04-20 15:33:52

+0

消息可能適用,也可能不適用。這個問題可能太複雜了,但這是一個很好的解決方案。 – 2011-04-20 15:34:38

1

最好的辦法是從孩子到父母進行某種引用,並在關閉孩子時更新父母。

或者您可以在孩子身上發生某種事件並讓家長聽這個事件。然後,當孩子關門時,你提出這個事件。

如果兩個ViewModel都是邏輯無關的,則使用消息傳遞。

[咆哮]不要人們甚至知道面向對象的基本原理或什麼? [/咆哮]

+1

我不認爲在這種情況下使用信使是不好的設計。這取決於任何數量的因素,但發送簡單的消息可能比在兩個虛擬機之間建立面向對象的關係要簡單得多並且更有效 – 2011-04-20 15:50:54

+0

我認爲問題在於沒有最佳實踐方法來做到這一點作爲MVVM模式的一部分。 – Will 2011-04-20 15:51:26

1

我幾天有同樣的問題;-)

前最後我用了一個調解員進行溝通都視圖模型。事實上,我使用MVVM Light的Messenger。

public void Search(object parameter) 
     { 
      ChildWindow window = new ChildWindow(); 

      SearchWindow pageSearch = new SearchWindow(); 

      window.Content = pageSearch; 
      window.Show(); 

      Messenger.Default.Register<Messages.CloseWindowMessage>(this, action => this.closeWindow(action)); 
     } 

之後,我定義的一切,我需要從主窗口知道消息:

public class CloseWindowMessage : MessageBase 
    { 
     public bool Result { get; set; } 
     public Model.Selected Selected { get; set; } 
    } 

最後的消息來自childwindow回你只需要註冊結果的消息和對象,你想要回來。

您應該從視圖的代碼隱藏中註冊以關閉窗口。

-1

我認爲在兩種視圖模型之間傳遞消息的最佳方式是事件編程。