I am developing a Windows Store apps game using WinRT Caliburn.Micro, and I am relying on the navigation framework.
I have view models for the game setup (define players) and the actual game. When navigating from the setup to the game, I want to pass the collection of players to the game view model. How can I do this?
Schematically, my view models currently look like this:
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);
}
}
Ideally, I would like to call InitializeScoreBoard
from within the GameViewModel
constructor, but as far as I have been able to tell it is not possible to pass the SetupGameViewModel.Players
collection to the GameViewModel
constructor.
The INavigationService.NavigateToViewModel<T>
(extension) method optionally takes an [object] parameter
argument, but this parameter does not seem to reach the view model constructor navigated to. And I cannot figure out how to explicitly call the GameViewModel.InitializeScoreBoard
method from the SetupGameViewModel.StartGame
method either, since the GameViewModel
has not been initialized at this stage.
In the end, I solved this by implementing a temporary event handler. It turned out that I could use the
NavigateToViewModel<T>(object)
overload to pass the player collection.From the Caliburn Micro discussion forum and MSDN documentation I get the impression that this approach is only guaranteed to work for "primitive" types, although in my scenario I have so far not detected any problems with it.
My
SetupGameViewModel.StartGame
method is now implemented as follows:And the very temporarily attached
NavigationServiceOnNavigated
event handler is implemented as follows:Not really the clean solution I had striven for, but at least it seems to work.
In Win Store Apps you can hand over complex objects between ViewModels with the help of the NavigationService. Only in Silverlight Apps you are restricted to objects which must be serializable to a string. This restriction does not exist in Win Store Apps.
In your case something like the following should work. In StartGame() the NavigationService is used to call the GameViewModel. The player list is handed over as a simple parameter. By convention this parameter will be assigned to a property Parameter of the destination ViewModel.
More detailed information on this subject can be found here: http://wp.qmatteoq.com/using-caliburn-micro-with-universal-windows-app-navigation/
OK, just putting it out there,
Caliburn.Micro
has unified navigation for WP8 and WinRT:And you can chain
WithParam
for multiple parameters. Now there are some constraints, not all types go through, I'm not quite sure what the exact reason for that is, but it has something to do how the navigation works in WinRT. There was a mention of it somewhere inCaliburn.Micro
discussion section.Anyway, you can navigate this way. Don't rely on constructor though, It will call
OnInitialize
andOnActivate
. So, just to cut it into the example:then in the
DetailsViewModel
:So, in pure theory, you could do:
in the setup and then:
In practice though, I don't think that passing a complex construct like that (collection of classes etc) is going to work.
More primitive types work just fine (
int
,string
,DateTime
etc., but e.g.URI
didn't work for me, was alwaysnull
), so worst-case scenario/workaround is, for example, to serialize thePlayers
list to a temp file before the navigation and pass the file path as string to deserialize in theGameViewModel
.There are people more involved in the framework roaming the SO, they might give you more valuable insight.