Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should I communicate between ViewModels?

I am using MVVM Light and have used the packaged messenger system to communicate between view models, however I have hit a bit of a dilemma! Basically when a user clicks on a customer record the corresponding view is opened and with it the CustomerViewModel is instantiated. At this point the CustomerViewModel requires the selected customers ID from the previous view model (ViewAllCustomersViewModel) so that it can get selected customers info which the view binds to (still following?). So initially my thought was too send that ID in a message from the ViewAllCustomersViewModel (where the customer to be viewed is selected) to the CustomerViewModel... HOWEVER, the CustomerViewModel is not instantiated to be able to receive the message until the view is loaded (at which point the message has already been broadcast)!

So, what would be the best way to solve this issue? So far I have considered the CustomerViewModel sending a request to the ViewAllCustomersViewModel once it has been instantiated (basically saying "I am ready to receive the message"), and then the ViewAllCustomersViewModel sending the ID back to the CustomerViewModel... but is this a necessary approach to solve this? It seems a bit ugly to me!

Otherwise, I was thinking is there another way to communicate which can account for the issue I am having? But then isn't this the whole point of the messaging system... to be able to communicate between view models? OR can I force the view model to be instantiated on start up? If so, how would that affect the ViewModelLocator?

I hope I have outlined the issue clearly, I have used fictional view model names for the purpose of the explanation... and please feel free to edit or suggest any additional information that you would like me to add!

like image 909
Sam Avatar asked Sep 26 '13 13:09

Sam


2 Answers

Did you try to communicate via your model? I was not able to read your topic until the end but this is how I communicate between ViewModels. Both View Models have the instance of session.

public ViewModel1(ISession session)
        {
            _session = session;           
        }

public ViewModel2(ISession session)
        {
            _session = session;           
        }

This way, when you test your application in BDD (behavior driven development), you can test your application without the view. The glue is the model.

As you can see on this picture, you should be able to test your application without the view. enter image description here

like image 105
Daniel Avatar answered Oct 21 '22 13:10

Daniel


I came across the same situation where two view model is communicating each other. I have used Microsoft PRISM framework to publish and Subscribe.

In your case CustomerViewModel is parent View and ViewAllCustomersViewModel is child view.

  1. Download prism framework "Microsoft.Practices.Prism.PubSubEvents.dll" from https://www.nuget.org/packages/Prism.PubSubEvents/

  2. Add prism reference to your project "Microsoft.Practices.Prism.PubSubEvents.dll"

  3. Create some custom class which is used for communication modem.

      class Notifications : PubSubEvent<string>
      {
    
      }
    
  4. Create IEventAggregator eventAggregator singleton instance for your project and initialize it.

      public sealed class SessionInfo
      {
            public  IEventAggregator eventHanlder;
    
            private SessionInfo (){
    
            }
    
            private static SessionInfo _instance = null;
    
            public static SessionInfo Instance{
                    get{
                     lock (lockObj){
                      if (_instance == null) {
                        _instance = new SessionInfo ();
                        _instance.eventHanlder= new EventAggregator();
                       }
                   }
                      return _instance;
                   }
                 }
                }
    
  5. Go to Popover model (ViewAllCustomersViwModel) button events handling and below codes in it.Now it has been published.

In ViewAllCustomersViwModel.cs:

      public void OnSelectedItem(Item item)
     {
            SessionInfo.Instance.eventHanlder.GetEvent<Notification>().Publish(item.id);

      }
  1. These event aggregator has to be subscribe where it is needed. So add below code on your Parent View model (CustomerViewModel)

CustomerViewModel.cs

       public class CustomerViewModel
      {
               public CustomerViewModel()
              {
                  SessionInfo.Instance.eventHanlder.GetEvent<Notifications>().Subscribe(OnReceivedNotification);

               }

        //Handling the notification 
    public void OnReceivedNotification(string itemId)
        {
            Debug.WriteLine("Item Id is :" + itemId);

        }


     }

For more information:

https://sites.google.com/site/greateindiaclub/mobil-apps/windows8/communicationbetweenviewmodelsinwindows8mvvmpattern

like image 29
Boobalan Avatar answered Oct 21 '22 13:10

Boobalan