如何在MVVM中使用相同的ViewModel拥有多个视图?

时间:2018-07-26 10:47:32

标签: c# wpf mvvm

我对WPF和MVVM都是陌生的,并且在尝试在两个单独的视图中将DataContext设置为我的ViewModel的同一实例时遇到一个问题。

这是因为:

<Window.DataContext>
    <local:ViewModel/>
</Window.DataContext>

将为每个视图创建视图模型的新实例。

为了解决这个问题,我决定创建一个类,该类存储我使用的每个ViewModel的静态实例。然后,在每个视图的cs文件中,我将DataContext设置为此静态类中的相应ViewModel。

这可行,但对于大型程序而言似乎不是最好的主意,在大型程序中可能同时需要ViewModel的多个实例。

解决此问题的更好方法是什么-是否有合理的方法使用同一个ViewModel实例拥有多个View?

或者这种方法是不好的做法-我是否应该为每个ViewModel设计一个带有一个View的程序?

谢谢!

4 个答案:

答案 0 :(得分:5)

您可以在App.xaml中实例化该视图模型,以便整个应用程序都可以访问它。

<Application.Resources>
    <local:ViewModel x:Key="sharedViewModel" />
</Application.Resources>

然后,在您想要使用该数据上下文的视图中,执行以下操作...

DataContext="{StaticResource sharedViewModel}"

答案 1 :(得分:1)

实现ViewModelLocator既简单又容易,也是推荐的方法之一。

想法已在ViewModelLocator类中定义了所有ViewModel,并在需要时访问ViewModel。在不同的视图中使用Same ViewModel不会成为问题。

    public class ViewModelLocator
{
         private MainWindowViewModel mainWindowViewModel;
  public MainWindowViewModel MainWindowViewModel
    {
        get
        {
            if (mainWindowViewModel == null)
                mainWindowViewModel = new MainWindowViewModel();

            return mainWindowViewModel;
        }
    }
    private DataFactoryViewModel dataFactoryViewModel;
 public DataFactoryViewModel DataFactoryViewModel
    {
        get
        {
            if (dataFactoryViewModel == null)
                dataFactoryViewModel = new DataFactoryViewModel();

            return dataFactoryViewModel;
        }
    }
}

App.xaml

    xmlns:core="clr-namespace:MyViewModelLocatorNamespace"

<Application.Resources>
    <core:ViewModelLocator x:Key="ViewModelLocator" />
</Application.Resources>

用法

<Window ...
  DataContext="{Binding Path=MainWindowViewModel, Source={StaticResource ViewModelLocator}}">

请参阅:So Question从那里复制的代码..因为我无法从我的项目中窃取代码。.

答案 2 :(得分:0)

我也有同样的问题,我找不到很好的答案。经过一段时间的思考,我得出的结论是,在大多数情况下,最好在视图模型和视图之间创建一对一的映射。因此,在这种情况下,我将创建两个独立的视图模型,这些视图模型继承自基本视图模型。这样,您可以放入基本视图模型中的所有常见内容,并添加可能与更具体的视图模型不同的任何字段或方法。如果视图模型确实等效,那么您可能想问自己为什么首先要有两个单独的视图。您可以考虑将它们合并为一个视图。可能需要两个单独的视图,但这只是要考虑的事情。

答案 3 :(得分:0)

我正在使用棱镜框架,并且也在寻找一种对多个(子)视图使用一个视图模型的解决方案。在棱镜中有两种可能的解决方案:

  1. 将视图模型定义为单例(代码异味)或
  2. 使用 RegionContext(有关完整说明,请参阅棱镜文档)

根据棱镜文档,我的解决方案如下所示。

在棱镜引导程序中:

Container.RegisterTypeForNavigation<MyView>("MyView");

在视图模型中:

private void DisplayView(string viewName)
{
    RegionManager.Regions["ContentRegion"].Context = this;  // set viewmodel
    RegionManager.RequestNavigate("ContentRegion", viewName);
}

在每个视图后面的代码中:

public MyView()
{
    InitializeComponent();
    ObservableObject<object> viewRegionContext = RegionContext.GetObservableContext(this);
    viewRegionContext.PropertyChanged += this.ViewRegionContext_OnPropertyChangedEvent;
}

private void ViewRegionContext_OnPropertyChangedEvent(object sender, PropertyChangedEventArgs args)
{
    if (args.PropertyName == "Value")
    {
        var context = (ObservableObject<object>)sender;
        DataContext = context.Value;  // get viewmodel as DataContext
    }
}