簡體   English   中英

我應該如何在ViewModels之間進行通信?

[英]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是子視圖。

  1. https://www.nuget.org/packages/Prism.PubSubEvents/下載prism框架“Microsoft.Practices.Prism.PubSubEvents.dll”

  2. 為項目“Microsoft.Practices.Prism.PubSubEvents.dll”添加prism引用

  3. 創建一些用於通信調制解調器的自定義類。

      class Notifications : PubSubEvent<string> { } 
  4. 為項目創建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; } } } 
  5. 轉到Popover模型(ViewAllCustomersViwModel)按鈕事件處理及其下面的代碼。現在它已經發布。

ViewAllCustomersViwModel.cs

      public void OnSelectedItem(Item item)
     {
            SessionInfo.Instance.eventHanlder.GetEvent<Notification>().Publish(item.id);

      }
  1. 這些事件聚合器必須在需要的地方進行訂閱。 因此,在您的父視圖模型(CustomerViewModel)上添加以下代碼

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);

        }


     }

欲獲得更多信息:

https://sites.google.com/site/greateindiaclub/mobil-apps/windows8/communicationbetweenviewmodelsinwindows8mvvmpattern

我相信標准的方法是通過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,但發現我有很多信息飛來飛去,我不喜歡使用“神奇”信使的感覺。 我所做的是概述為以下鏈接的答案

啟動時將數據傳遞給新ViewModel的最佳方法

現在我警告你,我回答了我自己的問題,並沒有人將其視為好的或壞的做法,但它適用於我的情況並且已經消除了對MVVM-Light Messenger的需求。 因為我的程序在我的實現中使用多個線程,所以我將存儲庫中的所有條目更改為Dictionarys,並將CurrentThread.ManagedThreadId作為Key。

到目前為止,我已經考慮過CustomerViewModel在實例化后向ViewAllCustomersViewModel發送請求(基本上說“我准備接收消息”),然后ViewAllCustomersViewModel將ID發送回CustomerViewModel ...

我會繼續這個想法。 與其他答案不同,它使Views,ViewModel和Models保持獨立且不知道其他人。 不是說其他​​答案是錯誤的,甚至是壞的,您的選項可以定義為以下一個或任何一個:個人偏好,團隊慣例,替換組件/模塊的長期MVVM目標,以及編碼的復雜性/易用性。

我上面引用的一個副作用,我更喜歡的是,您可以隨時請求,因為您已經設置了它。 因此,如果您更改何時非常輕松地執行該請求,或者您需要請求更新 ,則可以使用相同的通信體系結構。

最后,我更喜歡它,因為如果您更改模型或視圖或視圖模型 - 您保持在組件之間傳遞信息的相同核心概念。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM