2012-03-15 7 views
1

天気情報を表示するMVVM Windows電話アプリで作業しています。ViewModelsとIsolatedStorageSettings

アプリケーションが読み込まれると、MainPage.xamlが開きます。気象情報を取得するサービスを呼び出すと、そのデータをUIにバインドします。 FahrenheitとCelciusの両方の情報が返されますが、1つだけが表示されます。

設定ページで、ユーザは、華氏または摂氏のいずれかで温度を表示するように選択できます。 ユーザーはいつでもこの設定を変更でき、その設定はIsolatedStorageSettingsに保存されます。

問題があるのは、 ユーザーが[設定]ページに移動し、華氏または華氏のいずれかの設定を変更すると、この変更はメインページに反映されません。

この問題は、広い意味でこれについて考え始めました。これは、MVVMアプリケーションで問題が発生していることがわかります。ディスプレイはIsolatedStorageの設定によって異なります。 IsoStoreの設定が更新されるたびに、ViewModelはこれをどのように知っていますか? NavigationStackの設定ページからMainPageに戻ると、どのようにページの再バインドを強制できますか?

私のモデルのデータは変更されていません。表示したいデータのみが変更されています。

私はここで何かが欠けていますか?

ありがとうございます。 はアレックス

+0

これは私が直面している問題です。私はonNavigatedToメソッドを使ってそれを解決し、設定にバインドされた表示アイテムをリフレッシュしましたが、私はよりよい解決策を間違いなく望んでいます。 –

答えて

0

大丈夫ですので、私は解決策を考え出します。私がそれに着く前に、私はいくつかの背景を提供しましょう。私が働いているアプリケーションは、MVVM LightとWP7Contribの両方を使用しています。その場合、私はDIとMVVMLight ToolkitのためにFunqを使用しています。最初の質問を投稿した後、私はもう少し考えを与えました。私は、Windows Phoneで私はしばらくの間は、バックMIX2011からそれで

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

ローランBugnionでディープダイブMVVMと呼ばれ、彼はちょうどこの問題について語っ見た映像を(ビューモデルが同時に生きていない)を思い出し。問題の部分は19分ぐらいに始まります。

とにかく、私はそれを思い出して、App.xamlでViewModelロケータが公開されていることを認識した後、これは解決するための小さな問題になりました。ユーザーが設定ページで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; } 
} 

ですから、DisplayTemperatureプロパティから新しい値を取得するためにUIを通知するNotifyPropertyChangedイベントを追加する必要があります。

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

私は同様のことを試みましたが、表示が1ページにあるときは、別の「設定」ページに移動して設定を変更してから、戻るボタンを押してMainPageに戻り、MainPageには設定ページ。 –

+0

返事をありがとう。上のコードを例に挙げてみましょう。 DisplayTemperatureはMainViewModelにあり、IsCelsiumはSettingsViewModelにあります。 SettingsViewModelでIsCelsiumを設定すると、別のビューモデルでNotifyPropertyChangedを呼び出すことができません。 – Alex

+0

MVVMLightを使用している場合は、PropertyChangedメッセージが組み込まれており、変更を加えたビューモデルから送信し、他のビューモデルでサブスクライブすることができます。 MVVM Lightを使用していない場合は、このメッセージング動作を自分で実装できますが、MVVM Lightをお勧めします。 – Robaticus

0

Caliburn Microを見てください。同様のことを実装したり、CM自体を使用することができます。 CMを使うとき、私はこのことについても考えていないので、CMはそれをとても簡単にします。

あなたのViewModelがScreenから継承するとき、あなたが上書きできるライフサイクルイベントがあります。たとえば、VMがアクティブになるたびに、ViewModelがアクティブ化され、OnActivateが起動するのは、初めてOnInitializeが発生することです。 OnViewAttachedとOnViewLoadedもあります。

これらのメソッドは、ロジックを配置してデータを取り込むのに最適な場所です。

CMには、1つのプロパティまたはオブジェクトグラフ全体を簡単に廃棄してIsoまたは電話の状態にすることを許可するためのものもあります(special built in features)。

関連する問題