2013-12-14 15 views
5

Galasoft Mvvm Lightツールキットを使用して、Windows PhoneのMVVMパターンでアプリケーションをビルドします。私は、それぞれ独自のビューモデルを持っているページにする必要があります。ページ/ビューモデルコンストラクタのナビゲーションと再構築

ユーザーがアプリを起動すると、新しいゲームを選択して質問ページを開くことができます。これらのページにはそれぞれビューモデルがあり、すべてがviewmodellocatorを使用して動作します。その後、ユーザーは新しいゲームと質問との間で再びナビゲートして新しいゲームと質問を選択します。ビューモデル/ページは削除されません。ユーザーが2回目の質問や新しいゲームに入ると、viewmodelのコンストラクターが呼び出されず、コンストラクターの初期化が実行されず、ビューが正しく設定されません。私は、このような新しいゲームや質問への新しいナビゲーションなどナビゲーション、中backstackを削除しようとした

を試してみました

ソリューションは、新しいページをスピンアップし、それによって、コンストラクタをcaling必要があります。働いていない。

ビューでロードされたイベントを使用し、コンストラクタを呼び出します。働いていない。

従うことを試みた How to reset all instances in IOC Container しかし、それを動作させることができなかった、ちょうど私かもしれません。

誰でもこの問題を解決してもらえたら、どのように解決すればよいですか?

コード ここに例があります。質問を押してそこのボタンを一度押し、バックキーを使用します。質問をもう一度押します。あなたは数字が1になっているのを見ると、これは簡単に変更できます。しかし、ボタンをもう一度押すとエラーになります。突然2つのポップアップが表示されます。

したがって、ビューモデルを設定する正しい方法は何ですか。 newgameのビューは、古いゲームをリロードするとき、他の値を使うとき、そして新しいゲームを開始したいときに使用されるからです。あなたが理解したいと思っています:)

この例は、viewmodelページに戻るたびにポップアップカウントが上がっている問題を示しています。 https://www.dropbox.com/s/gjbz0l8rmsxqzrd/PhoneApp8.rar

のViewModelロケータ 私は以下のコードで見られる3つのviewmodelsを使用して、私の現在のプロジェクトで午前:

using GalaSoft.MvvmLight; 
using GalaSoft.MvvmLight.Ioc; 
using Microsoft.Practices.ServiceLocation; 

namespace MVVMTestApp.ViewModel 
{ 
public class ViewModelLocator 
{ 
    public ViewModelLocator() 
    { 
     //Holder styr på ViewModels 
     ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); 

     //Tilføj linje her for hver ViewModel 
     SimpleIoc.Default.Register<MainViewModel>(); 
     SimpleIoc.Default.Register<MainViewModelTest>(); 
     SimpleIoc.Default.Register<MenuViewModel>(); 
    } 

    //Tilføj metode som denne for hver ViewModel 
    public MainViewModel Map 
    { 
     get 
     { 
      return ServiceLocator.Current.GetInstance<MainViewModel>(); 
     } 
    } 

    public MainViewModelTest Main 
    { 
     get 
     { 
      return ServiceLocator.Current.GetInstance<MainViewModelTest>(); 
     } 
    } 

    public MenuViewModel Menu 
    { 
     get 
     { 
      return ServiceLocator.Current.GetInstance<MenuViewModel>(); 
     } 
    } 

    public static void Cleanup() 
    { 
      // TODO Clear the ViewModels 
    } 
} 

私はIOCコンテナ内のすべてのインスタンスをリセットする上記の参考文献のリンクに見てきました。しかし、どのようにキーが動作するのかが不明で、ビューから移動するときにクリーンアップ機能が呼び出されるようにする方法。私は同時にすべてのビューモデルをきれいにしたくないからです。

ナビゲーションと

をviewmodelbinding私はのNavigationServiceと戻るボタンを使用して前後に移動

DataContext="{Binding Source={StaticResource Locator},Path=Map}" 

としてビューに自分のviewmodelをバインドします。

NavigationService.Navigate(new Uri("/View/MainPage.xaml", UriKind.Relative)); 

とページ

protected override void OnNavigatedTo(NavigationEventArgs e) 
    { 
     //e.Content = NavigationMode.New; 
     //e.NavigationMode = NavigationMode(
     ViewModel.MainViewModel test = new ViewModel.MainViewModel(); 
     GC.Collect(); 
     base.OnNavigatedTo(e); 
    } 

とゲームからメニューまでに:メニューからゲームに

protected override void OnNavigatedFrom(NavigationEventArgs e) 
    { 
     //e.NavigationMode = NavigationMode. 
     this.DataContext = null; 
     GC.Collect(); 
     base.OnNavigatedFrom(e); 
     //test = null; 
    } 

とメニューに私は、ガベージコレクタを起動します。わかりましたように、問題を解決するためにMVVM構造を壊します。

+0

問題を示す特定のサンプルを投稿できる場合は、より具体的な回答が得られると思います。しかし、一般的には、ビューモデルのポイントはページ読み込みの間にデータを永続化することだと思うので、第2ページビューが最初のビューからのデータを保持することは驚くべきではありません。これを処理するには、コンストラクタからページ初期化の一部をコンストラクタから呼び出された関数に移動し、ページがロードされたイベントからも処理します。 – BobHy

+0

それはまさに私がやったことです。しかし、メモリの問題があります。なぜなら、ビューモデルはナビゲート時にクリアされないからです。 datacontextがビューに設定されているので、私は後ろのビューモデルへのアクセスを取得できません。私がこれまでにしなければならなかったのは、datacontext = nullを設定し、GC.collect()を呼び出すことでした。しかし、これは良い方法ではありません。私は正しい方法が何であるかを知りたがっていました。 – JTIM

+1

あなたが現在何をしているかを示すサンプルを投稿してください。与えられたページP1のためのビューモデルV1が、P1が2回目にロードされたときにまだメモリ内にあることは、起こりそうなことである。あなたはP1.DataContextの他のビューモデルを見ていますか? – BobHy

答えて

3

ViewModelLocatorのプロパティは、シングルトンを返します。

private int questCount; 

public Question Quest 
{ 
    get 
    { 
     return ServiceLocator.Current.GetInstance<Question>((++questCount).ToString()); 
    } 
} 

ただし、結果としてViewModelキャッシングが発生する可能性があるたびに、プロパティを新しいインスタンスに戻すようにします。あなたはあなたがリンクした答えに密接に従って、未使用のViewModelをリリースする必要があります。これは簡単な結果のためにあまりにも多くのコードで私の意見になります。 Windows PhoneでSimpleIocninjectまたはunityなど)の代わりに使用できる他のIOCコンテナがありますが、これはお客様のニーズに適しています。

:単純なプロジェクト(夫婦・オブ・ページアプリ)、特にIOCコンテナで多くの経験を持っていない場合には、私はすべてのことSimpleIoc配線を放棄し、ただコンストラクタを呼び出すことを助言するには

public Question Quest 
{ 
    get { return new Question(); } 
} 
+0

あなたの返事をありがとう、私のプロジェクトはかなり大きく、私は3つのビューモデルを使用しています。クリーンアップを呼び出す方法がわからず、静的であってもクリーンアップがすべての変数に対して確実に行われるように、クリーンアップ機能を実装しようとしました。 リンク先のコードを実行して動作させることはできますが、キーがどのように機能しているかについてはわかりません。だから私はコードを使用するための多くではない、私は維持する方法を知らない。だから、私はMVVMライトを使用しているのでSimpleIocを使用したいと思いますが、その方法はわかりません。私は私のViewmodellocatorと私の質問を更新します。 – JTIM

+0

@JTIM非常にシンプルなコンストラクタを持つ3つのViewModel(あなたのSimpleIoc設定で判断する)は、IOCコンテナを使用しない*確かに*のケースです。明示的なコンストラクタ呼び出しでは、はっきり理解できるコードがはるかに少なくなります。 – lisp

+0

@JTIM SimpleIoc - GetInstanceは同じインスタンスを返します。指定されたキーを持つGetInstanceは、指定されたキーに対して同じインスタンスを生成します。登録解除では、キーに割り当てられたインスタンスを削除できます。これは単なるSimpleIoc仕様です。これはいくつかのシナリオでは役に立ちますが、適用するのが難しい場合もあります。 SimpleIocは、MVVMLightのヘルパーの1つにすぎません。すべてのプロジェクトですべてを使用する必要はありません。 ViewModelLocatorは簡単に記述することができます。 – lisp

関連する問題