2013-03-06 17 views
5

WinRT Caliburn.Microを使用してWindows Storeアプリケーションゲームを開発しており、ナビゲーションフレームワークに頼っています。WinRT Caliburn.Microを使用してナビゲートされたビューモデルにパラメータを渡す方法は?

私はゲーム設定(プレイヤーを定義する)と実際のゲームのビューモデルを持っています。セットアップからゲームにナビゲートするとき、私はプレイヤーのコレクションをゲームビューモデルに渡したいと思います。これどうやってするの?

を模式的に、私の見解モデルは、現在、次のようになります。

public class SetupGameViewModel : NavigationViewModelBase 
{ 
    public SetupGameViewModel(INavigationService ns) : base(ns) { } 

    public IObservableCollection<Player> Players { get; set; } 

    public void StartGame() 
    { 
     // This is as far as I've got... 
     base.NavigationService.NavigateToViewModel<GameViewModel>(); 

     // How can I pass the Players collection from here to the GameViewModel? 
    } 
} 

public class GameViewModel : NavigationViewModelBase 
{ 
    public GameViewModel(INavigationService ns) : base(ns) { } 

    public ScoreBoardViewModel ScoreBoard { get; private set; } 

    public void InitializeScoreBoard(IEnumerable<Player> players) 
    { 
     ScoreBoard = new ScoreBoardViewModel(players); 
    } 
} 

理想的には、私はコンストラクタ内からInitializeScoreBoardを呼び出すしたいと思いますが、私の知る限り、それを伝えることができたとすることはできませんSetupGameViewModel.Playersコレクションをコンストラクタに渡します。

INavigationService.NavigateToViewModel<T>(オプション)メソッドは、オプションで[object] parameter引数をとりますが、このパラメータは、ナビゲートされたビューモデルのコンストラクタには達していないようです。 はこの段階では初期化されていないため、GameViewModel.InitializeScoreBoardメソッドをSetupGameViewModel.StartGameメソッドから明示的に呼び出す方法もわかりません。

答えて

4

最後に、私は一時的なイベントハンドラを実装してこれを解決しました。私はプレーヤーのコレクションを渡すためにNavigateToViewModel<T>(object)過負荷を使用することができたことが判明しました。

Caliburn Micro discussion forumMSDN documentationから、このアプローチは「プリミティブ」タイプでしか動作しないことが保証されていますが、私のシナリオではこれまでのところ問題は検出されていません。

次のように私のSetupGameViewModel.StartGame方法が実装されました:本当に

private static void NavigationServiceOnNavigated(object sender, NavigationEventArgs args) 
{ 
    FrameworkElement view; 
    GameViewModel gameViewModel; 
    if ((view = args.Content as FrameworkElement) == null || 
     (gameViewModel = view.DataContext as GameViewModel) == null) return; 

    gameViewModel.InitializeScoreBoard(args.Parameter as IEnumerable<Player>); 
} 

ない私は努力していたきれいな解決策:次のように

public void StartGame() 
{ 
    base.NavigationService.Navigated += NavigationServiceOnNavigated; 
    base.NavigationService.NavigateToViewModel<GameViewModel>(Players); 
    base.NavigationService.Navigated -= NavigationServiceOnNavigated; 
} 

そしては非常に一時的に添付NavigationServiceOnNavigatedイベントハンドラが実装されていますしかし、少なくともそれは動作するようです。

+1

それをありがとう、それは私の時間の多くを保存しました。 – jimpanzer

+0

Rob自身からのこの記事では、複雑なデシリアライゼーションをサポートしていないUriに基づいて動作する、Windows Phoneのナビゲーションベースのシステムのためだと説明しています。 http://caliburnmicro.codeplex.com/discussions/267562 –

6

OK、ただそこに出し、Caliburn.MicroはWP8とWinRTのための統一されたナビゲーションを持っています

NavigationService.UriFor<TargetViewModel>().WithParam(x => x.TargetProperty, ValueToPass).Navigate(); 

そして、あなたは複数のパラメータのためのチェーンWithParamをすることができます。今やいくつかの制約がありますが、すべてのタイプが通過するわけではありませんが、私はその正確な理由は何かをはっきりとは分かりませんが、WinRTでのナビゲーションの仕組みについては何かを持っています。 Caliburn.Micro discussion sectionのどこかにそれの言及がありました。

とにかく、この方法でナビゲートできます。コンストラクタに頼らないでください。OnInitializeOnActivateを呼び出します。 DetailsViewModelで、その後

NavigationService.UriFor<DetailsViewModel>().WithParam(x => x.Id, SelectedDetailsId).Navigate(); 

::だから、単なる一例にそれをカットする

protected override void OnInitialize() 
{ 
    //Here you'll have Id property initialized to 'SelectedDetailsId' from the previous screen. 
} 

ので、純粋理論的には、あなたができる:セットアップで

NavigationService.UriFor<GameViewModel>().WithParam(x => x.Players, Players).Navigate(); 

をし、次に:

public class GameViewModel 
{ 
    public GameViewModel(INavigationService ns) : base(ns) 
    { 
     //It would probably be good to initialize Players here to avoid null 
    } 

    public ScoreBoardViewModel ScoreBoard { get; private set; } 

    public IObservableCollection<Player> Players {get;set;} 

    protected void OnInitialize() 
    { 
     //If everything goes as expected, Players should be populated now. 
     ScoreBoard = new ScoreBoard(Players); 
    } 
} 

In pしかし、私はそのような複雑なコンストラクト(クラスのコレクションなど)を渡すことはうまくいくとは思わない。

より原始的なタイプは(intstringDateTimeなどが、例えばURIが私のために動作しませんでした、いつもnullた)うまく動作するので、最悪のシナリオ/回避策はPlayersをシリアル化するために、例えば、ナビゲーションの前に一時ファイルにリストし、でデシリアライズする文字列としてファイルパスを渡します。

SOをローミングしているフレームワークに関わる人がいれば、より貴重な洞察を与えるかもしれません。

+0

多くのおかげで、これは非常に有用な情報だった、私はこの応答から多くのことを学びました。しかし、あなたが疑うように、 'Players'コレクションは' WithParam'を介して受け入れられないようです。私は現在、Navigatedイベントのローカルハンドラを定義する非常に厄介な解決法を実装しています。イベント引数はナビゲーションコンテンツを提供し、コンテンツの 'DataContext'が私のビューモデルであると暗黙のうちに仮定します。それでも、誰かがこの問題に対してより信頼性の高い解決策を用意していると良いでしょう。 –

+1

ところで、私はあなたが[ここ](http://caliburnmicro.codeplex.com/discussions/393238)という議論を見つけたと思う。 –

+0

@AndersGustafssonそうですね、これはまさにこの議論です。私が言ったように、Caliburn.Microを使ってデータをどこかに保存してから、ある種の鍵で再作成することとは別に、現時点ではもっと良い解決策を知らない。上記の議論から - [マイクロソフトでさえそれを嫌う](http://msdn.microsoft.com/en-us/library/windows/apps/hh702394.aspx)、一般的にサポートされている* ... –

2

Winストアアプリケーションでは、NavigationServiceの助けを借りてViewModel間で複雑なオブジェクトを引き渡すことができます。 Silverlightアプリケーションでのみ、文字列に直列化可能でなければならないオブジェクトに制限されています。この制限はWin Store Appsには存在しません。

あなたの場合、次のようなものが動作するはずです。 StartGame()では、NavigationServiceを使用してGameViewModelを呼び出します。プレイヤーリストは単純なパラメーターとして渡されます。規約によって、このパラメータは、宛先ViewModelのプロパティParameterに割り当てられます。このテーマに関する

より詳細な情報はここで見つけることができます

public class SetupGameViewModel : Screen 
{ 
    private readonly INavigationService _navigationService; 

    public MainPageViewModel(INavigationService navigationService) 
    { 
     _navigationService = navigationService; 
    } 

    public IObservableCollection<Player> Players { get; set; } 

    public void StartGame() 
    { 
     _navigationService.NavigateToViewModel<GameViewModel>(Players); 
    } 

    ... 
} 


public class GameViewModel : Screen 
{ 
    private IObservableCollection<Player> _parameter; 

    public IObservableCollection<Player> Parameter 
    { 
     get { return _parameter; } 
     set 
     { 
      if (value.Equals(_parameter)) return; 
      _parameter = value; 
      NotifyOfPropertyChange(() => Parameter); 
     } 
    } 

    protected override void OnActivate() 
    { 
     // do something with the player list 
     // ... 
    } 

    ... 
} 
http://wp.qmatteoq.com/using-caliburn-micro-with-universal-windows-app-navigation/

+0

ありがとう、それは私のWindows 10 UWPアプリケーションの答えです。そして、はい、目的地ビューモデル(サンプルの 'GameViewModel')のプロパティは' Parameter'と呼ばれなければなりません。これは規約のようです。 –

関連する問題