2013-01-17 85 views
1

我們的新項目始於使用ViewModelLocator與ViewModel結合視圖的View第一個模式。從視圖優先改變爲視圖模型優先 - 我如何處理構造函數依賴注入

我想更改爲ViewModel的第一個模式。

這裏是我的視圖模型構造:

public DeviceSelectionViewModel(IDataModel dataModel, IMessenger messenger) 
{ 
    if (dataModel == null) throw new ArgumentNullException("dataModel"); 
    if (messenger == null) throw new ArgumentNullException("messenger"); 

    Selector = new PlantDataTemplateSelector(); 
    PlantSelector = new PlantNodesSelector(); 
    Plants = new List<Plant>(0); 

    messenger = messenger; 
    messenger.Register<PlantDataLoadedMessage>(this, m => DispatcherHelper.CheckBeginInvokeOnUI(() => OnPlantDataLoaded(m.Plants))); 

    RefreshData(_dataModel); 
} 

下面是我現在首先用視圖模型選擇適當的視圖模型。

public class MainViewModel : Module 
{ 

    public MainViewModel() 
    { 
     SelectedView = new DeviceSelectionViewModel(); 
    } 

    public ViewModelBase SelectedView { get; set; } 

} 

隨着視圖第一,我從來沒有直接通過代碼直接調用ViewModel,所以構造函數依賴注入工作正常。

現在我通過控制器ViewModel調用ViewModel,它需要ViewModel構造函數的2個參數。

在這裏適當的玩法是在控制器視圖模型中保存引用並將它們傳遞給構造函數?在這種情況下,我錯過了一些關於DI如何工作的內容?

我仍與DI(Ninject)和MVVM把拼在一起,所以要那種:)

回答

1

我們有同樣的問題。

您有以下選擇:

  • MainViewModel創建DeviceViewModel提供值所需的參數
  • MainViewModel被早已解決DeviceViewModel

第一個變種增加耦合的情況下DeviceViewModel僅適用於View綁定。如果MainViewModelDeviceViewModel通信,那麼耦合已暗示,除非MainViewModel通過某個接口看到DeviceViewModel什麼不可避免地需要第二個選項。

第一種方法的另一個問題是,在某些情況下,嵌套虛擬機可能需要更多值來創建父虛擬機所需的值。
這可以通過擴展父虛擬機構造函數來包含這些附加參數來解決。但是,當構建複雜的虛擬機圖形(儘管從未在實踐中)根虛擬機的構造函數會變得臃腫。

我們現在有兩種選擇的組合。

我們所有的ViewModel繼承自ViewModelBase抽象類。它有幾個重載的構造函數,其中大部分都是IViewModelFactory作爲輸入。所以我們可以要求工廠創建ViewModel需要。 Wee決定不用擔心返回的類型,只返回創建的ViewModel的類型,僅包含其創建。所以這不是真的DI。

我們也使用Messanger,但我們的ViewModels不能顯式發送消息,只能訂閱消息。我們故意這樣做,以限制特定虛擬機可以發送(甚至訂閱)的一組消息。

+0

我得到的第一個選擇,但我無法繞過第二個選擇。你能好好談談那一點嗎? – faldeland

+0

@faldeland我更新了我的答案 –

+0

此信息非常有幫助。我希望儘可能遵循最佳做法。我正在尋找一種可靠的方式來通過MainViewModel進行導航。我相信我會像你一樣深入到底。我希望我能找到一個有這些實踐的開源項目。 – faldeland