[英]How should I communicate between ViewModels?
我正在使用MVVM Light,並使用打包的messenger系統在視圖模型之間進行通信,但是我遇到了一些兩難的問題! 基本上,當用戶單擊客戶記錄時,將打開相應的視圖,並使用它來實例化CustomerViewModel 。 此時, CustomerViewModel需要來自先前視圖模型( ViewAllCustomersViewModel )的所選客戶ID,以便它可以獲取視圖所綁定的選定客戶信息(仍然跟隨?)。 所以最初我的想法是將來自ViewAllCustomersViewModel (選擇要查看的客戶)的消息中的ID發送到CustomerViewModel ...但是, CustomerViewModel未實例化以便能夠在加載視圖之前接收消息(此時消息已經播出)!
那么,解決這個問題的最佳方法是什么? 到目前為止,我已經考慮過CustomerViewModel在實例化后向ViewAllCustomersViewModel發送請求(基本上說“我准備接收消息”),然后ViewAllCustomersViewModel將ID發送回CustomerViewModel ......但這是一個解決這個問題的必要方法? 這對我來說似乎有點難看!
否則,我在想是否有另一種溝通方式可以解釋我遇到的問題? 但是,這不是消息系統的全部意義......能夠在視圖模型之間進行通信嗎? 或者我可以強制在啟動時實例化視圖模型嗎? 如果是這樣,那將如何影響ViewModelLocator ?
我希望我已經清楚地概述了這個問題,為了解釋的目的,我使用了虛構的視圖模型名稱...請隨時編輯或建議您希望我添加的任何其他信息!
您是否嘗試通過您的模型進行交流? 直到最后我才能閱讀您的主題,但這是我在ViewModels之間進行通信的方式。 兩個View Models都具有會話實例。
public ViewModel1(ISession session)
{
_session = session;
}
public ViewModel2(ISession session)
{
_session = session;
}
這樣,當您在BDD(行為驅動開發)中測試應用程序時,您可以在沒有視圖的情況下測試應用程序。 膠水是模型。
正如您在此圖片中看到的那樣,您應該能夠在沒有視圖的情況下測試您的應用程序。
我遇到了兩種視圖模型相互通信的情況。 我使用Microsoft PRISM框架發布和訂閱。
在您的情況下,CustomerViewModel是父View,ViewAllCustomersViewModel是子視圖。
從https://www.nuget.org/packages/Prism.PubSubEvents/下載prism框架“Microsoft.Practices.Prism.PubSubEvents.dll”
為項目“Microsoft.Practices.Prism.PubSubEvents.dll”添加prism引用
創建一些用於通信調制解調器的自定義類。
class Notifications : PubSubEvent<string> { }
為項目創建IEventAggregator eventAggregator
單例實例並初始化它。
public sealed class SessionInfo { public IEventAggregator eventHanlder; private SessionInfo (){ } private static SessionInfo _instance = null; public static SessionInfo Instance{ get{ lock (lockObj){ if (_instance == null) { _instance = new SessionInfo (); _instance.eventHanlder= new EventAggregator(); } } return _instance; } } }
轉到Popover模型(ViewAllCustomersViwModel)按鈕事件處理及其下面的代碼。現在它已經發布。
在ViewAllCustomersViwModel.cs
:
public void OnSelectedItem(Item item)
{
SessionInfo.Instance.eventHanlder.GetEvent<Notification>().Publish(item.id);
}
CustomerViewModel.cs
public class CustomerViewModel
{
public CustomerViewModel()
{
SessionInfo.Instance.eventHanlder.GetEvent<Notifications>().Subscribe(OnReceivedNotification);
}
//Handling the notification
public void OnReceivedNotification(string itemId)
{
Debug.WriteLine("Item Id is :" + itemId);
}
}
欲獲得更多信息:
我相信標准的方法是通過View傳遞它。 根據您實例化視圖的方式,可能是要在XAML,構造函數參數或其他任何內容中綁定的DependencyProperty。 然后View將它傳遞給它的ViewModel(將其推送到VM,而不是解決方法:ViewModel不應該知道View)。 這樣您就可以得到一個獨立的封閉組件(您的視圖),而外部代碼不知道它的內部實現(即ViewModel)。
在XAML中它可以是類似的東西
<ListBox x:Name="customers" />
<CustomerView Customer="{Binding SelectedItem, ElementName=customers}" />
然后在CustomerPropertyChanged處理程序中將值推送到ViewModel。
就個人而言,我曾經使用MVVM-Light Messenger,但發現我有很多信息飛來飛去,我不喜歡使用“神奇”信使的感覺。 我所做的是概述為以下鏈接的答案
現在我警告你,我回答了我自己的問題,並沒有人將其視為好的或壞的做法,但它適用於我的情況並且已經消除了對MVVM-Light Messenger的需求。 因為我的程序在我的實現中使用多個線程,所以我將存儲庫中的所有條目更改為Dictionarys,並將CurrentThread.ManagedThreadId作為Key。
到目前為止,我已經考慮過CustomerViewModel在實例化后向ViewAllCustomersViewModel發送請求(基本上說“我准備接收消息”),然后ViewAllCustomersViewModel將ID發送回CustomerViewModel ...
我會繼續這個想法。 與其他答案不同,它使Views,ViewModel和Models保持獨立且不知道其他人。 不是說其他答案是錯誤的,甚至是壞的,您的選項可以定義為以下一個或任何一個:個人偏好,團隊慣例,替換組件/模塊的長期MVVM目標,以及編碼的復雜性/易用性。
我上面引用的一個副作用,我更喜歡的是,您可以隨時請求,因為您已經設置了它。 因此,如果您更改何時非常輕松地執行該請求,或者您需要請求更新 ,則可以使用相同的通信體系結構。
最后,我更喜歡它,因為如果您更改模型或視圖或視圖模型 - 您保持在組件之間傳遞信息的相同核心概念。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.