MVVM Light, Windows Phone, View & ViewModel Between Pages

I have a page in which you basically select a set of parameters (configuration), and then go to the next page, where you do something like Using the MVVM Light toolkit, I have a viewmodel that binds to the presentation of the first page. when the user clicks the button, he redirects to another view, which will be the second page, i.e. :.

Page2Command = new DelegateCommand((obj) => Messenger.Default.Send<Uri>(new Uri("/DoStuffView.xaml", UriKind.Relative), Common.CommonResources.GoToDoStuffRequest)) }); 

The problem is that the view model for the second view (the way I see it) has several parameters in the constructor, which mainly depend on the configuration installed on the first page.

i.e.

 public DoStuffViewModel(ICollection<Note> availableNotes, SoundMappers soundType) { } 

The problem is here. How can I create an instance of a model with this data that was dynamically selected by the user on the first page?

I cannot use the ViewModelLocator template, which provides MVVM light, since these view models do not have any dependencies, they are on their own (or they can extract data from db, file or any other, but they do not have dynamic input data). I could do this through the view constructor, instantiate the view model and assign the newly created viewmodel to the DataSource, but I think it's not very nice to do this. offers?

+4
source share
3 answers

As I can see, you are sending messsage using the Messenger class, so you are familiar with messaging in MVVM mode. You must define your own message type, which should accept your parameters from page 1:

  public class Page2ViewModelCreateMessage : MessageBase { public ICollection<Note> AvailableNotes{get;set;} public SoundMappers SoundType{get;set;} public Page2ViewModelCreateMessage () { } public Page2ViewModelCreateMessage(ICollection<Note> availableNotes, SoundMappers soundType) { this.AvailableNotes = availableNotes; this.SoundType = soundType; } } 

You need to send an instance of Page2ViewModelCreateMessage with parameters and send it when navigating:

 var message = new Page2ViewModelCreateMessage(myAvailableNotes, mySoundType) Messenger.Default.Send(message); 

On page 2, you need to register to receive a message like Page2ViewModelCreateMessage:

  Messenger.Default.Register<Page2ViewModelCreateMessage>(this, OnPage2ViewModelCreateMessage); .. public void OnPage2ViewModelCreateMessage(Page2ViewModelCreateMessage message) { var page2ViewModel = new Page2ViewModel(messsage.AvailableNotes, message.SoundType); } 

As you can see, I can replace your DoStuffViewModel with Page2ViewModel to be more clear.

Hope this helps you.

NOTE. I do not guarantee that the code will work as written in notepad.

+3
source

The way I do this is to have a central controller class that all ViewModels know about through the interface. Then I set the state to this before the phone navigates for me. Each ViewModel requests this center class for the state it needs.

There are several advantages to me:

  • This allows me to have non-static ViewModels.
  • I can use Ninject to inject a specific implementation of the controller class and use it as a singleton.
  • Most importantly, when burial, I only need to capture the current ViewModel and controller class.

I ran into a messaging problem when my ViewModel was a registered listener because I was View First and not ViewModel. At first I had to use ViewModel static links. Otherwise, the ViewModel was not created in time to receive the message.

I use the controller class in combination with messages (it is mainly the recipient of all messages around the user interface), so in the future, if I reorganize, I do not need to change much, only the message recipients.

Think about it, the controller class is also my navigation receiver, as I have some kind of custom navigation code that skips paging on certain pages, etc.

Here is an example of my current setup:

 public interface IController { Foo SelectedFoo { get; } } public class ViewModel { private IController _controller; public ViewModel(IController controller) { _controller = controller; } private void LoadData() { // Using selected foo, we load the bars. var bars = LoadBars(_controller.SelectedFoo); } } 
+1
source

You can use the PhoneApplicationService dictionary to save the data you need when navigating from the first event, and analyze it when navigating the second page. You can also use this data in your ViewModels. Something like that:

  PhoneApplicationService.Current.State["DatatFromFirstPage"] = data; 

and when going to the second page:

  if (PhoneApplicationService.Current.State.ContainsKey("DatatFromFirstPage")) { var dataUsedOnSeconPage= PhoneApplicationService.Current.State["DatatFromFirstPage"]; } 

you can use this data globally throughout the application

0
source

All Articles