1

I have 2 questions.

First=> How can i pass value between 2 ViewModels ?

For example, I m adding data and showing it into the MainPAGE, and simultaneously I want to show the same data ( Observable Collection ) in the ChildPAGE too. Inside the ChildPAGE Xaml I assigned the BindingContext to ViewModel and I assigned listview’s data source to that Observable Collection .But I couldn’t make it work . I tried some examples, but I couldn’t manage it to work. If the data load in the ChildPAGE’s constructor then it works else doesn’t work. I thought , I would improve the performance with using one ObservableCollection, but I think, the mechanism in MVVM is different. So how can I use one ObservableCollection in 2 pages.

Second => How can I pass data between ViewModels without using the constructor. Example: I Have 2 Pages ( MainPage and ChidPage) and 2 ViewModels ( MainVM and ChildVM ) .

Situation => If I would pass data from MainPage to ChildPage , I would send data within the constructor .But I want to get data from Childpage to MainPage . So PopAsync doesn’t have a constructor. I also tried EventHandler but it doesn’t work.

Is the only solution is Messaging center? Or what do you advice for better performance? Also does the MessagingCenter reduces the performance because of high usage of RAM? NOTE: ( I want to learn the mvvm architecture, so I don’t want to use other MVVM Frameworks. I want to get the idea of MVVM and C# comprehensively.) Thanks in advance

Fethullah Kaya
  • 194
  • 4
  • 16
  • Typically, `await navService.PushAsync(new MyPage2(dataToShare));` is used to pass data between pages/ underlying VMs. In your case, I would use the local storage to cache the data and simply load it in the child/main page. With every udpate or delete, the cache would be refreshed. – bit Jan 13 '20 at 23:20
  • If you are really that much into high performance critical applications then stay away from Xamarin and go to C++, otherwise those questions are legitimate but also irrelevant. At the end of the day Xamarin's implantation may change and some thing may work quicker in the future and some may work slower. – Ivan Ičin Jan 13 '20 at 23:54
  • Do yourself a favor and check out Prism for Xamarin Forms. This will get you started quick: https://xamgirl.com/prism-in-xamarin-forms-step-by-step-part-1/ – Sean Anderson Jan 14 '20 at 02:03
  • @Except messagecenter, you can take a look [FreshMvvm](https://github.com/rid00z/FreshMvvm), and MessageCenter does reduce performance:https://www.betterask.erni/news-room/profiling-memory-leaks-in-xamarin-forms/ – Cherry Bu - MSFT Jan 14 '20 at 04:15

2 Answers2

1
  1. You normally use await navService.PushAsync(new MyPage2(dataToShare)); to pass data between pages/VMs. This involves using constructors. Here is a simple example of it: https://stackoverflow.com/a/47873920/1508398

  2. Since you don't want to use constructors, you may load the data on your child page from your service. Alternatively, you may cache the data on the local storage (client-side) and simply load it from there in your child/main page.

bit
  • 4,407
  • 1
  • 28
  • 50
1

You could create a model class that both view models depend on. The model itself would hold the observable collection, while the view models reference the observable collection. This is a good way to share data across various view models throughout the life of your app. Usually you will want to make the model a singleton to ensure that it really is the same data.

If you don't want to use messaging center, you can use an MVVM framework which comes with other benefits. I use Prism to simplify navigation and you can pass navigation parameters along.

Finally, and this is not the best option usually, you may maintain data in the App object. You can set values in the Properties collection. This is not advisable for complex objects.

EDIT First you would have some data transfer object which the ObservableCollection would contain, unless you're just holding integers or something.

public class MyDTO
{
  //fields for Data Transfer Object  
}

DTO's are often among your models, but sometimes you need a composite class to hold DTO's and collections of DTO's

Here is a simple Model that would contain your ObservableCollection

public class MyCollectionModel
{
    #region Singleton Pattern
    private MyCollectionModel()
    {
    }
    public static MyCollectionModel Instance { get; } = new MyCollectionModel();
    #endregion
    private ObservableCollection<MyDTO> _dtos;
    public ObservableCollection<MyDTO> MyObservableCollection
    {
        get { return _dtos; }
        set { _dtos = value; }
    }
}

Note that this implements the Singleton pattern. It could even implment INotifyPropertyChanged as well.

Next your view models, imagine a MyVM1 and MyVM2, would reference the ObservableCollection in your Model with something like this.

    public class MyVM1 : INotifyPropertyChanged // Do the same with MyVM2, which would be the binding context for view 2
    {
        private MyCollectionModel _model;
        public MyVM1 ()
        {
            _model = MyCollectionModel.Instance;
        }
        private ObservableCollection<MyDTO> myVar;
        public ObservableCollection<MyDTO> MyProperty //Bind to this in your View1
        {
            get 
            { 
                return _model.MyObservableCollection; 
            }
            set
            {
                myVar = value;
                NotifyPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

I'm leaving quite a few things out here, and don't really have time to build an entire project just to test. I hope this helps.

Blanthor
  • 2,568
  • 8
  • 48
  • 66
  • thank u for your help sir. if you have time and if it s possible, could u make a very little example ? i m planing use Prism too. but first, i m trying to get the main idea. – Fethullah Kaya Jan 14 '20 at 21:47
  • 1
    I added a hopefully helpful example under EDIT. This is a non-Prism example. – Blanthor Jan 14 '20 at 23:45
  • Thank you sir. it works great. i added constructor of MyCollectionModel() it was returning null so i added this private MyCollectionModel() { MyObservableCollection = new ObservableCollection(); } if you want, you can edit the code. thanks – Fethullah Kaya Jan 15 '20 at 12:06
  • By the way, observable collection works great, but string or integer doesnt work. i tried many things, but i couldnt make it work. – Fethullah Kaya Jan 15 '20 at 23:25