如何在Xamarin.Forms中将多个页面的BindingContext设置为相同的ViewModel?

4

我是Xamarin.Forms的新手,想使用MVVM模式和XAML创建一个跨平台的应用程序。在我的表单项目(pcl)中,我想将MainPage和将来的多个页面的BindingContext设置为同一个ViewModel。这可能吗?让我展示一下我说的是什么。下面是我之前一个WPF项目的代码片段(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
}

ViewModel的内容并不重要。通过这种结构,我可以将同一个 _ViewModel 对象设置为多个窗口的 DataContext 。在Xamarin.Forms中有相应的替代方法吗?

以下是我PCL项目中的简单代码(App.cs):

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

以下是来自于MainPage.xaml.cs的代码:

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

我理解这是设置页面的BindingContext的正确方式,但我想知道每次打开MainPage是否会创建一个新的具有默认值的ViewModel对象。而且我不明白其他页面如何能够使用与MainPage相同的ViewModel对象。在我看来,以上的WPF项目代码逻辑简单明了,只有一个ViewModel对象。我必须为每个页面创建不同的ViewModel类吗?对我来说这似乎是错误的。
所以,是否有一种方法可以在后续添加到项目中的每个页面中使用的某个地方 - 也许是在App.cs中 - 创建一个ViewModel对象?我怀疑这一点。我希望我的表述清楚,提前感谢您!
1个回答

7
可以将页面的BindingContext设置为应用程序管理的对象;ViewModel不必在构造函数中创建(或设置);这只是很多示例代码所做的事情。有几种方法可以采取:使用ViewModelLocator创建单个ViewModel并向使用该ViewModelLocator连接上下文的任何视图公开它、依赖注入容器(例如MvvmLight提供的SimpleIOC),其中ViewModel被注册为单例、在页面工厂中手动设置等等。一个使用在构造函数中引用的ViewModelLocator的简单示例如下:
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;
    }
}

您还可以通过ViewModelLocator上的setter,从IOC容器中获取等方式设置_myViewModel成员。


非常感谢!这种ViewModelLocator方法真是太棒了! - Gábor Birkás
是的,它非常有用。你甚至可以使用ViewModelLocator模式,在不同的情况下使用特定的ViewModel(比如说,在调试版本中使用一个“模拟”ViewModel)。 - Andy Hopper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接