1

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

我的问题描述:

  1. 我们有一个包含多个视图(用户控件)的对话窗口。单击下一步和返回将在此对话框中前后移动,类似于向导。

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

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

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

我考虑过以下几点:

  1. 静态类
  2. 单身 - ehhhh
  3. 在视图之间传递参数(尽管这很困难,因为 nextlocation 和 previouslocation 非常通用)。
  4. 中介模式?我对中介者模式的问题是我不想在视图之间“交流”。我只希望所有视图共享相同的数据源。
  5. 观察者模式?如果我使用 ObservableCollections 并实施 INotifyPropertyChanged,那么我应该不需要通知任何人更改吗?

请让我知道您可能需要帮助我解决此问题的其他信息,我很乐意提供。

我并不是真的在寻找代码示例,因为我是设计者。虽然如果代码示例可以帮助解释设计,我完全赞成。

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

提前致谢!!

4

5 回答 5

5

就像 Randolf 说的那样,DI 会起作用。我使用 MEF 和使用 CreationPolicy 共享的构造函数注入来执行此操作。你只需要把你想为你处理的东西 4views 放在一个导出类中。那是多么容易:)

顺便说一句:中介者模式是视图模型而不是视图之间的“通信”。

[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 个视图模型引用了您的核心数据

于 2012-09-17T05:54:19.290 回答
3

我知道自从提出这个问题以来已经有很长时间了,但是在为同样的问题苦苦挣扎之后, RayBurns 的 Response here真的帮助我真正简单而轻松地意识到没有必要觉得你必须制作视图模型对于您的每个用户控件。我现在将一个视图模型用于一堆关于 a演变的不同视图,Collection作为一系列相关信息,其状态都彼此相关

否则,如果您真的必须在视图模型之间共享数据,我绝对会像 @blindmeis 演示的那样将其作为构造函数的参数。

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

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

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

于 2013-02-14T18:28:29.400 回答
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可以在您第一次创建时在您的子 ViewModel 中设置,或者根据您的喜好DialogWizardViews切换时。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根本不需要。

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

于 2012-09-14T19:45:04.897 回答
1

在我看来,您的视图共享相同的Model,这应该是可观察的,并且您的 ViewModel 都应该以不同的方式表示 Model。

如果您的模型和视图模型实现了观察者模式,那似乎是最干净、“最正确”的方法。

于 2012-09-14T19:04:26.110 回答
0

一个简单的“依赖注入”应该可以工作。第二个视图模型的构造函数依赖于注入到他的构造函数中的共享数据参数,依此类推。

于 2012-09-14T19:03:09.113 回答