简体   繁体   中英

How to set BindingContext of multiple pages to the same ViewModel in Xamarin.Forms?

I'm new to Xamarin.Forms and I'd like to create a cross-platform app using MVVM pattern and XAML. In my forms project (pcl) I'd like to set the BindingContext of my MainPage and also multiple pages in the future to the same ViewModel. Is this possible? Let me show what I'm talking about. Below is a code snippet from an earlier WPF project of mine ( App.xaml.cs ):

public partial class App : Application
{
    private MainWindow _MainWindow;
    private MyViewModel _ViewModel;

    public App()
    {
        _ViewModel = new MyViewModel();

        _ViewModel.SomeEvent += new System.EventHandler(ViewModel_SomeEvent);
    }
}



protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    _MainWindow = new MainWindow();
    _MainWindow.DataContext = _ViewModel;
    _MainWindow.Show();         
}

private void ViewModel_SomeEvent(object sender, EventArgs e)
{
     //Do something
}

The contents of the ViewModel are not important. With this structure I was able to set the same _ViewModel object as the DataContext of multiple windows. Is there an equivalent to this in Xamarin.Forms?

Here is a simple code from my pcl project ( App.cs ):

public class App
{
    public static Page GetMainPage ()
    {   
        return new MainPage();
    }
} 

And the code from MainPage.xaml.cs :

public partial class MainPage : ContentPage
{   
    public MainPage ()
    {
        InitializeComponent ();
        BindingContext = new MyViewModel ();
    }
}

I understand this is a proper way to set the BindingContext of a page but I'm wondering if this will result in creating a new ViewModel object with default values every time I open MainPage . And also I don't understand how other pages will be able to use the same ViewModel object as MainPage . In my opinion the above WPF project code is logical and simple. One ViewModel object and that's it. Do I have to create different ViewModel classes to every page? That's just seems wrong to me.

So is there a way to somehow create one ViewModel object - maybe in App.cs ? I doubt it. - somewhere to be used by every page I might want to add to the project later. I hope I've been clear and thank you in advance!

Yes, you can certainly set the BindingContext of a page to an object that your application manages; the ViewModel does not have to be created (or even set) inside the constructor; that just happens to be what a lot of sample code does.

There are several approaches you can take for: a ViewModelLocator that creates a single ViewModel and exposes it to any view that uses that ViewModelLocator to wire up the binding context, a dependency injection container (like the SimpleIOC that MvvmLight provides) with the ViewModel registered as a singleton, manually setting it in a Page factory, and so on.

A simple example using a ViewModelLocator referenced in the ctor would be:

public static class ViewModelLocator
{
    private static MyViewModel _myViewModel = new MyViewModel();
    public static MyViewModel MainViewModel
    {
        get
        {
            return _myViewModel;
        } 
    } 
}

...

public partial class MainView : ContentPage
{
    public MainView()
    {
        BindingContext = ViewModelLocator.MainViewModel;
    }
}

...

public partial class SomeOtherView : ContentPage
{
    public SomeOtherView()
    {
        BindingContext = ViewModelLocator.MainViewModel;
    }
}

You can also have it so that the _myViewModel member is set through a setter on the ViewModelLocator, pull it from an IOC container, etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM