2012-02-14 65 views
5

在我的WPF應用程序中,我使用MVVM模式和依賴注入。具有依賴注入的MVVM ViewModels中的陳舊數據

從數據庫準備數據的ViewModels將存儲庫注入構造函數。他們還使用構造函數中的存儲庫數據填充屬性。

ViewModel都是在ViewModelLocator類的靜態構造函數中創建的,ViewModelLocator類用來綁定到ViewModel。

這有以下缺點:

  1. 在視圖中的數據永遠不會更新,即使不關閉並重新打開它們時,因爲視圖模型實例始終是相同的。
  2. 打開第一個視圖後,所有的ViewModel都將被實例化,並且它們需要從數據庫中加載所需的數據。

我能想到的兩種方法來解決這些問題:

  1. 讓每視圖模型實現的是從數據庫中讀取數據並初始化屬性的方法 - 而不是在構造函數中這樣做。這需要每次打開視圖時調用該方法。這介紹了我不喜歡的temporal coupling
  2. 以每次調用ViewModelLocator上相應屬性時創建請求的ViewModel的方式實現ViewModelLocator。我不喜歡這種方法,因爲我的組合根不會在程序啓動時執行,但會在程序實例的整個生命週期中傳播。

有沒有解決此問題的另一種方法?其他人如何解決這個問題?

回答

2

在其創建的視圖模型要求上的每個ViewModelLocator相應的屬性被稱爲一次這樣的方式實現的ViewModelLocator。

這是我通常在這種情況下采取的更多方法。然而,我沒有通過ViewModel的DI組成ViewModelLocator,而是組成了創建ViewModel的工廠。

我不喜歡這種方法,因爲我的合成根不會在程序啓動時執行,但會在程序實例的整個生命週期中傳播。

這得到「解決」,至少部分,通過組成工廠而不是類型本身。構圖在啓動時發生一次,但創建可以在ViewModel的任何時候發生。

例如,使用MEF,您可以切換導入,直接使用ExportFactory<T>而不是其類型。隨着NonShared Creation Policy,您可以根據需要構建ViewModels,並始終使用新數據,而不存在暫時耦合問題。

+0

謝謝你的回答。爲我的每個ViewModel設立一個工廠似乎有些過火,因爲工廠只能在一個地方使用,而且目前沒有必要。此外,除了container.Resolve之外,他們不會做任何其他事情。由於ViewModelLocator仍然是容器的唯一使用位置,所以我更喜歡在抽象工廠上調用'container.Resolve',因爲即使在這種情況下,容器也不會泄漏到應用程序代碼中。如果容器的配置不正確,我認爲抽象工廠的唯一優勢就是在啓動時會立即出現錯誤(續) – 2012-02-14 19:49:50

+0

(續)。 – 2012-02-14 19:50:07

0

我的摘要ViewModelBase基類需要一個抽象的RefreshDataCore()方法。可以通過在ViewModel實例上調用Refresh()或通過設置IsDirty標誌來手動調用此方法。當ViewModel.IsVisible爲true並且IsDirty被設置時,Refresh()也將被調用。

這樣,只要視圖模型變得可見,您就可以對數據進行惰性刷新,並且還可以通過調用Refresh()手動調用刷新。

下面的示例。 (我已經離開INPC通知了爲簡單起見)

public abstract class ViewModelBase 
{ 
    //Pull your data from the repository here 
    protected abstract void RefreshCore(); 
    public void Refresh() 
    { 
      RefreshCore(); 
      IsDirty = false; 
    } 

    private bool _isVisible = false; 
    //DataBind this to the visibility of element "hosting" your view model 
    public bool IsVisible 
    { 
     get { return _isVisible; } 
     set 
     { 
       if (_isVisible == value) 
        return; 


       _isVisible = value; 
       if (IsVisible && IsDirty) 
        Refresh(); 
     } 
    } 

    private bool _isDirty = true; 
    public bool IsDirty 
    { 
     get { return _isDirty; } 
     set 
     { 
      if (_isDirty == value) 
       return; 

      _isDirty = value; 
      if (IsVisible && IsDirty) 
       Refresh(); 
     } 
    } 

} 
+1

你如何解決時間耦合問題?你只是住在一起,並根據需要總是調用刷新? – 2012-02-14 19:18:13

+0

我有一個ApplicationViewModel定期檢查數據的狀態並設置適當的IsDirty標誌(但只有​​可見視圖模型將主動刷新) 出於性能原因,ApplicationViewModel還包含本地數據緩存,其他ViewModelBase實例讀取它們的RefreshDataCore()方法。你有完全的靈活性來實現這一點,因爲你需要,雖然 – cordialgerm 2012-02-14 19:22:48

+0

感謝您的答案。但是,我沒有看到時間耦合解決,所以這不是我將要使用的。 – 2012-02-14 19:44:22