2012-03-15 66 views
1

我正在使用顯示天氣信息的MVVM Windows手機應用程序。ViewModels和IsolatedStorageSettings

當應用程序加載時,它打開MainPage.xaml。它會調用服務來獲取天氣信息並將該數據綁定到UI。華氏和Celcius信息都會返回,但只顯示一個。

在設置頁面上,用戶可以選擇以華氏度或攝氏度查看溫度。 用戶可以隨時更改此設置並將其存儲在IsolatedStorageSettings中。

我遇到的問題是這樣的: 當用戶導航到設置頁面並且改變他們對華氏或者Celcius的偏好時,這個改變並不反映在主頁面上。

這個問題開始讓我在更廣泛的背景下思考這個問題。我可以看到這是任何MVVM應用程序中的問題,其中顯示取決於IsolatedStorage中的某些設置。任何時候IsoStore中的任何設置都會更新,ViewModels如何知道這一點?當我在NavigationStack中從設置頁面返回到MainPage時,如何強制頁面重新綁定?

我模型中的數據沒有改變,只有我想要顯示的數據發生了變化。

我在這裏錯過了一些簡單的東西嗎?

在此先感謝。 亞歷

+0

這也是我遇到的問題。我已經通過使用onNavigatedTo方法解決了它,並刷新了綁定到設置的顯示項目,但我肯定會喜歡更好的解決方案。 – 2012-03-15 15:10:58

回答

0

好的,所以我想出了一個解決方案。在我開始之前,讓我提供一些背景知識。我正在使用的應用程序使用MVVM Light和WP7Contrib。既然如此,我正在使用Funq進行DI和MVVMLight Toolkit。在我發佈我的最初問題後,我給了這個問題更多的想法。我記得我看了一會兒從MIX2011回叫深潛MVVM與洛朗•比尼翁

http://channel9.msdn.com/Events/MIX/MIX11/OPN03

在它的視頻,他在Windows Phone談到剛剛這個問題(視圖模型沒有住在同一時間) 。有問題的部分在19分鐘左右開始。

無論如何,在我想起並意識到ViewModel定位器暴露在App.xaml中後,這成爲了一個小問題來解決。當用戶在設置頁面上更改Fahrenheit/Celcius選項時,我只需通過ViewModelLocator獲取對MainViewModel的引用,並重置綁定到UI的集合,從而導致綁定更新。

public bool AddOrUpdateValue(string Key, Object value) 
    { 
     bool valueChanged = false; 

     // If the key exists 
     if (settings.Contains(Key)) 
     { 
      // If the value has changed 
      if (settings[Key] != value) 
      { 
       // Store the new value 
       settings[Key] = value; 
       valueChanged = true; 
      } 
     } 
      // Otherwise create the key. 
     else 
     { 
      settings.Add(Key, value); 
      valueChanged = true; 
     } 
     return valueChanged; 
    } 


    public bool ImperialSetting 
    { 
     get 
     { 
      return GetValueOrDefault<bool>(ImperialSettingKeyName, ImperialSettingDefault); 
     } 
     set 
     { 
      if (AddOrUpdateValue(ImperialSettingKeyName, value)) 
      { 
       Save(); 
       RaisePropertyChanged("ImperialSettingText"); 
       var vml = new ViewModelLocator(); 
       vml.MainViewModel.Cities = (App.Current as App).Cities; 
      } 
     } 
    } 

這是我的錯誤,我沒有意識到我可以通過ViewModelLocator訪問viewModel。希望這篇文章能夠爲我解決這個問題上的時間。

0

也許你有這樣的代碼:

public double DisplayTemperature 
{ 
    get { return (IsCelsium) ? Celsium : Fahrenheit; } 
} 

而且IsCelsium是:

public double IsCelsium 
{ 
    get { return (bool)settings["IsCelsium"]; } 
    set { settings["IsCelsium"] = value; } 
} 

所以你需要添加NotifyPropertyChanged事件通知UI從DisplayTemperature屬性來獲取新的價值觀:

public double IsCelsium 
{ 
    get { return (bool)settings["IsCelsium"]; } 
    set 
    { 
     settings["IsCelsium"] = value; 
     NotifyPropertyChanged("DisplayTemperature"); 
    } 
} 
+0

我嘗試過類似的方法,但是當顯示位於一個頁面上時,您可以導航到另一個「設置」頁面並更改設置,然後點擊返回按鈕返回到MainPage,MainPage不會收到對設置進行的更改設置頁面。 – 2012-03-15 15:53:11

+0

感謝您的回覆。讓我們以上面的代碼爲例。 DisplayTemperature位於MainViewModel中,IsCelsium位於SettingsViewModel中。當我在SettingsViewModel上設置IsCelsium時,我無法在另一個視圖模型上調用NotifyPropertyChanged。 – Alex 2012-03-15 15:53:13

+0

如果您使用的是MVVMLight,那麼您可以從進行更改並在其他視圖模型中訂閱的視圖模型發送內置的PropertyChanged消息。如果你不使用MVVM Light,你可以自己實現這個消息傳遞行爲,但我會推薦MVVM Light。 – Robaticus 2012-03-15 19:29:46

0

看看Caliburn Micro。你可以實現類似的東西或者使用CM本身。當使用CM時,我甚至不考慮這個東西,CM使它變得如此簡單。

當您的ViewModel繼承自Screen時,會有生命週期事件觸發您可以覆蓋的事件。例如,OnInitialize首次啓動ViewModel,並且OnActivate在每次激活VM時觸發。還有OnViewAttached和OnViewLoaded。

這些方法是放置邏輯來填充或重新填充數據的理想場所。

CM還有一些special built in features允許人們輕鬆地將單個屬性或整個對象圖表邏輯化爲Iso或電話狀態。