2017-01-20 172 views
1

我有類,A,B,C,dMVVM:的ViewModels的鬆散耦合

A具有到E和B以及C和D

的列表在AViewModel這些露出的參考在樹上。

A的視圖看起來像圖片中的樣子。

enter image description here

當應顯示選擇的相應視圖的節點。

沒有爲E,B,C和d

的ViewModels我的問題如下:

例如E是所選擇的節點。我將它作爲「object SelectedItem」存儲在AViewModel中。 什麼是以鬆散耦合方式創建EViewModel的最佳方式,以便我不想在AViewModel中引用EViewModel。

更新:

我在想一個解決方案,但我從來沒有見過,在其他地方:

例如,我可以只露出我的波蘇斯(B,C,d,e)從AViewModel。而在XAML中,我可以將ContentControl直接綁定到這些對象上。有了轉換器,我可以有一個BViewModel,當我綁定到B等。

+0

能否請您發表您的XAML所以我們沒有推倒重來? – lokusking

回答

0

如果您的A視圖顯示「列表」,再加上所選視圖,那麼在AViewModel中使用EViewModel引用是完全可以接受的。 ViewModels可能是觀點的「反映」。因此,如果A視圖將包含EView,則AViewModel可能包含EViewModel。您只需嵌套視圖模型,以創建與視圖圖層中相同的樹。最後,我要做的不是引用E或B,...在AViewModel中,而是僅引用EViewModel,BViewModel,...所以AView列表不顯示模型類,但顯示ViewModel類。您的SelectedItem被輸入爲ViewModel,您可以直接將「Display」視圖部件綁定到SelectedItem。然後,您可以在視圖圖層上使用正確的DataTemplate來顯示相應的視圖。希望它有幫助

+0

這就是我目前正在做的:)但我總覺得這可以以更好的方式完成。 – jannagy02

1

在MVVM應用程序中以鬆散耦合的方式在視圖模型和其他組件之間進行通信的常用方法是使用事件聚合器或信使。有關更多信息,請參閱以下鏈接。

使用事件聚合模式視圖模式之間進行通信:https://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/

MVVM - Messenger和查看服務在MVVM:https://msdn.microsoft.com/en-us/magazine/jj694937.aspx

另一種選擇是使用你注入視圖模型與共享服務:https://social.msdn.microsoft.com/Forums/en-US/22907a0f-d805-4195-8272-7c284b72d2ee/example-of-using-shared-services-prism?forum=wpf

使用事件聚合,Messenger或共享服務意味着你可以刪除視圖模型類之間的所有引用。

代替具有來回彼此強引用視圖模型類,每個視圖模型只知道單個事件聚合器/信使/共享服務和只與這一個連通。視圖模型A可以發送任何其他視圖模型可以訂閱的消息以在內部收聽和處理。

我的問題是關於創建視圖模型的實例話題的最佳做法,而無需緊密耦合,不是鬆耦合的ViewModels

,而無需創建創建另一個視圖模型的實例之間的通信字符串耦合是不可能的。如果一個視圖模型創建另一個視圖模型的實例,則它們通過定義強烈耦合。爲了防止這種情況,你可以用注射的接口類型,其他視圖模型工具,例如:

public ViewModelB(IViewModelA viewModelA) 
{ 
    //... 
} 

然後ViewModelB依賴於一個接口類型,而不是一個具體的實現ViewModelA的視圖模型。這是一個有點不是做這樣的事情更好,因爲再ViewModelA和ViewModelB永遠是 - 如上所述 - 強耦合到對方:

public ViewModelB() 
{ 
    _viewModelA = new ViewModellA(); 
} 

但如果你真的關心你的視圖模型類之間的鬆耦合,你應該擺脫直接引用並開始使用事件聚合器或信使來溝通它們。

+0

我的問題是關於創建視圖模型的實例話題的最佳做法,而無需一個thigt耦合,不是鬆耦合的ViewModels之間的通信。 – jannagy02

+0

這是不可能的。如果一個視圖模型創建另一個視圖模型的實例,則它們通過定義強烈耦合。查看我編輯的答案以獲取更多信息。 – mm8

+0

@ jannagy02使用工廠方法並返回(實例)接口。或者像棱鏡一樣使用DI容器 - 您請求一個類型(使用接口)並返回一個具體類型。但是,對於你指定什麼這聽起來像B,C,d和E都是波蘇斯(這可能與自己的ViewModels包裹) - 這是確定的AViewModel瞭解他們,因爲它的工作是塑造,改造和呈現數據風景。 – slugster