在ViewModels之间共享集合

时间:2012-09-14 19:00:03

标签: c# wpf mvvm mediator data-sharing

我已经搜索过,没有任何东西可以帮助我到达我需要的地方。

我的问题描述:

  1. 我们有一个对话窗口,可以托管多个视图(usercontrols)。单击下一步和后退将在此对话框中向前和向后移动,类似于向导。

  2. 在6个对话框中,其中4个引用相同的核心数据。例如,我们将说一个ObservableCollection

  3. 在这种情况下,我有4个viewModel,它们都需要引用同一个ObservableCollection。每次我进入“向导”对话框中的新步骤时,我都不想保存然后重新加载列表。

  4. 我的问题是实现这一目标的最佳/最实用的方法是什么。

    我考虑过以下事项:

    1. 静态课程
    2. Singleton - ehhhh
    3. 在视图之间传递参数(尽管这很难,因为nextlocation和previouslocation非常通用)。
    4. 中介模式?调解器模式的问题在于我不想在视图之间“通信”。我只是希望所有视图共享相同的数据源。
    5. 观察者模式?如果我正在使用ObservableCollections并实现INotifyPropertyChanged,那么我不需要通知任何人我应该做出改变吗?
    6. 请告诉我您可能需要的其他信息以帮助我,我很乐意提供。

      我不是在寻找代码示例,因为我正在设计。虽然代码示例可以帮助解释设计,但我全都是为了它。

      最后,EventAggregator不是一个选项,因为我没有使用任何框架(除非我没有正确理解EventAggregator)。

      提前致谢!!

5 个答案:

答案 0 :(得分:5)

像兰多夫说DI会起作用。我用MEF和CreationPolicy共享的构造函数注入执行此操作。你只需要把你想要的东西放在一个出口类中。这有多容易:)

和btw:介体模式是在视图模型之间“通信”而不是视图。

[Export]
public class MyClassWichHasDataSharedFor4Views {}

public class Viewmodel1
{
   [ImportingContructor] 
   public Viewmodel1(MyClassWichHasDataSharedFor4Views shareddata)
   {}
}

public class Viewmodel2
{
   [ImportingContructor] 
   public Viewmodel2(MyClassWichHasDataSharedFor4Views shareddata)
   {}
}

public class Viewmodel3
{
   [ImportingContructor] 
   public Viewmodel3(MyClassWichHasDataSharedFor4Views shareddata)
   {}
}

public class Viewmodel4
{
   [ImportingContructor] 
   public Viewmodel4(MyClassWichHasDataSharedFor4Views shareddata)
   {}
}

现在4个视图模型引用了您的核心数据

答案 1 :(得分:3)

根据对话框的说明及其工作原理,我会有一个ViewModel来控制整个“向导”。

DialogWizardViewModel将包含:

  • ObservableCollection<SomeModel> Data
  • ObservableCollection<ViewModelBase> DialogWizardViews
  • ViewModelBase SelectedView
  • ICommand NextCommand
  • ICommand BackCommand

您的DialogView将包含ContentControl绑定到SelectedView的内容,而您的Next / Back命令只会切换SelectedView } {到DialogWizardViews

中的下一个或上一个视图

例如,

<DockPanel>
    <StackPanel DockPanel.Dock="Bottom" 
                Orientation="Horizontal" 
                HorizontalAlignment="Center">
        <Button Command="{Binding BackCommand}" Content="Back" />
        <Button Command="{Binding NextCommand}" Content="Next" />
    </StackPanel>

    <ContentControl Content="{Binding SelectedView}" />
</DockPanel>

Data可以在您第一次创建DialogWizardViews时设置您的孩子ViewModel,或者根据您的喜好切换SelectedView

DialogWizardViews = new ObservableCollection<ViewModelBase>()
{
    new DialogViewModel1(Data),
    new DialogViewModel2(),
    new DialogViewModel3(Data),
    new DialogViewModel4(Data),
    new DialogViewModel5(Data),
    new DialogViewModel6()
};

SelectedView = DialogWizardViews.FirstOrDefault();

请记住,对于MVVM,您的ViewModels 是您的应用程序,而Views只是为用户提供了一个用户友好的界面,以便与ViewModel进行交互。理想情况下,您应该能够从测试脚本或控制台应用程序运行整个应用程序,而根本不需要View

如果你需要传递一些东西,它应该由应用程序层次结构中的某个父对象处理,或者使用某种通信系统,如Prism的EventAggregator或MVVM Light Messenger。您不需要使用整个框架来使用这些对象 - 您可以选择您感兴趣的部分。

答案 2 :(得分:3)

我知道自从提出这个问题已经有很长一段时间了,但是在经历了同样的问题之后经历了很多努力 RayBurns's Response here真正帮助我实现了一个非常简单和轻松的认识,即没有必要为每个用户控件制作视图模型。我现在使用一个viewmodel来查看Collection进化的一堆不同视图,作为一系列相关信息,其状态都与彼此相关

否则,如果你真的必须在viewmodels之间共享数据,我绝对会把这作为构造函数的参数,比如@blindmeis演示。

DataContexts首先如何设置和共享(对我而言)的本质似乎在于View的代码隐藏。这是我放在那里的唯一东西,但它允许我在Entity Framework中共享ObjectContexts,与一个视图 - 许多视图模型建立Master-Details关系等。

形成一个存储库“更高层”也很棒,但要小心你在数据到达目的地之前多次复制/传输数据。

Anywho,那是我的两分钱。希望能帮助到你。在经历了很多不适之后,我最终发现自己正在融合。

答案 3 :(得分:1)

在我看来,你的观点共享相同的 Model ,这应该是可观察的,而你的ViewModel应该以不同的方式代表模型。

如果你的Model和ViewModel实现了Observer模式,那似乎是最干净,最“最直接”的方法。

答案 4 :(得分:0)

简单的“依赖注入”应该有效。第二个viewmodel的构造函数依赖于注入其构造函数的Shared Data参数,依此类推。

相关问题