Passing data when using ViewModel-driven navigation

Jul 25, 2011 at 10:24 PM

Hi Tony

Is there a 'correct' MVVM way to pass data between ViewModels when using ViewModel-driven navigation in SL? I have the basics of navigation (as per your March blog post) working fine, but I need to pass details of the current entitiy when navigating from one page to another. I have this working using a static variable in a public class (which I update before navigating and read from after naviating) but this seems rather inelegant. Is there a more 'correct' way?

Thanks!

Cheers - Graham

Jul 26, 2011 at 6:46 PM

Hi Graham,

The best way is to use the message bus! :-) It's easy. ViewModelBase has a SendMessage method you call to send a message.  It also has a RegisterToReceiveMessage method that you can use to receive messages.  Each of these accepts a NotificationEventArgs<TOutGoing>, where you can specify any type for TOutGoing.  There is also an overload that has a TIncoming type argument, for when you want to call back the sender and pass a piece of data.

Tony

Jul 26, 2011 at 11:43 PM

Brilliant Tony - thanks! You really do seem to have thought of everything... :)

Unless I've missed something though I'm in a bit of a Catch 22. My code in the ViewModel I'm navigatig from calls SendMessage to perfrom the navigation and then SendMessage to pass data. It seems to be the case though that the ViewModel I'm navigating to only gets instantiated after all the code has finished running in the ViewModel I'm navigating from, so the ViewModel I'm navigating to never gets the message containing the data. I've got myself in a muddle thinking about how to solve this and I'd be very grateful if you could point me in the right direction.

Many thanks Tony!

Cheers - Graham

Jul 30, 2011 at 2:06 PM
Edited Jul 30, 2011 at 3:42 PM

Hello Graham,

I see what you're trying to do. This is a problem related to the SL navigation system, in which the view is created when you set the Frame's Source property. One way to deal with it is to compose query string parameters and append them to the page name, but that only works for simole values, such as OrderId. There is no equivalent to an HTTP post, where you can pass a complex object such as Order.

The way I've approached this is to use a static dictionary with the page name as the key and another dictionary (string, object) as the value for the key-value pairs (property / value). The destination page reads the values in the NavigatedTo event and then clears them.

Let me know if this makes sense. I'm contemplating incorporating this mechanism into a future version of the toolkit. :-) 

Cheers,

Tony

P.S. You still would use the MessageBus in the case where you want to drive navigation based on logic in a ViewModel. For example, based on an action by the user you might want to decide which page to load next.  That is where you would send a message from the ViewModel to the MainPageViewModel passing the name of the ViewModel you want to go to.

Jul 31, 2011 at 11:34 PM

Here is an update, with a link to a sample app and the code that passes data during navigation:
http://simplemvvmtoolkit.codeplex.com/discussions/267069

Cheers,

Tony