Wpf 如何使用集合构造MVVM?

Wpf 如何使用集合构造MVVM?,wpf,mvvm,Wpf,Mvvm,当涉及列表/集合时,我很难理解如何应用MVVM模式 假设MainModel有一些属性和方法,以及包含其他DetailModel对象的列表。可以添加、删除或重新排序DetailModel对象 main视图将显示一些与根模型相关的控件,并从列表中填充一个ListBox。通过DetailModelViewUserControl,每个项目都有自己的子视图 最后,还有一个MainViewModel。它的属性由MainModel的属性和方法支持,绑定到主视图,更改通知使所有内容保持同步。(到目前为止,我对这

当涉及列表/集合时,我很难理解如何应用MVVM模式

假设
MainModel
有一些属性和方法,以及包含其他
DetailModel
对象的列表。可以添加、删除或重新排序
DetailModel
对象

main视图
将显示一些与根模型相关的控件,并从列表中填充一个
ListBox
。通过
DetailModelView
UserControl
,每个项目都有自己的子视图

最后,还有一个
MainViewModel
。它的属性由
MainModel
的属性和方法支持,绑定到主视图,更改通知使所有内容保持同步。(到目前为止,我对这种模式感到满意——如果我遗漏了一些基本的东西,我会更详细地说明这一点……)

当涉及到处理清单时,我感到困惑。我遇到过几个例子,其中
MainViewModel
只向视图公开
DetailModels
列表,而
DetailModelViews
直接绑定到模型。这起作用,但有问题。它没有始终如一地遵循这种模式(不存在
DetailViewModel
),它驱使我在我的细节模型中包含一些与UI相关的代码。我似乎很清楚,
MainViewModel
应该为UI绑定一个
DetailViewModels
列表,但我一直在思考如何实现这样的事情


应该如何管理这两个列表(
DetailModels
DetailViewModels
)?我真的很困惑,我最初在哪里填充
DetailViewModel
列表,以及我应该如何处理添加、删除或更改项目顺序以保持同步

您有一个单独的
DetailModels
列表和
DetailViewModels
列表是正确的。DetailViewModels列表应该是类型为
ObservableCollection
的属性。您可以在设置模型时(或者在构建时,如果将模型传递到ViewModel的构造函数中,则在构建时)填充可观察列表

private observedcollection m_详细信息;
公共数字细节
{
获取{return m_details;}
}
您可以订阅m_详细信息。。在这里,您可以处理模型中列表内容的重新排序


我希望这会有所帮助。

根据我的经验,如果您正在进行简单的只读演示,例如在组合框中显示字符串属性,则可以将模型对象公开到视图中。如果存在涉及对象的任何类型的实际UI(特别是涉及双向数据绑定的UI),则需要一个视图模型

通常,主VM的构造函数如下所示:

public MasterViewModel(MasterModel m)
{
   _Model = m;
   _Detail = new ObservableCollection<DetailViewModel>(m.Detail);
}
公共主视图模型(主模型m)
{
_模型=m;
_细节=新的可观察收集(m.细节);
}
其中,
MasterModel.Detail
DetailModel
对象的集合,
\u Detail
是向视图公开的
Detail
属性的支持字段

就添加、删除和重新排序此列表中的项目而言,在UI中,至少可以通过
MasterViewModel
上的命令来完成,该命令必须同时操作
MasterModel.Detail
MasterViewModel.Detail
。这有点痛苦,但除非每次更改
MasterModel.Detail
后都要重新填充
masterview model.Detail
,否则这是不可避免的


另一方面,如果您一直想知道“为什么我需要为视图模型编写单元测试?”,现在您知道了。

通常
模型
只不过是数据对象。它们不应该包含任何代码来执行诸如从列表中添加/删除项目之类的操作。这是视图模型的作业

在您的情况下,我将创建一个具有以下属性的
MainViewModel

  • 可观察到的收集详细信息
  • ICommand AddDetailCommand
  • ICommand RemoveDetailCommand
如果您的
MainModel
类是数据对象,您可以公开它,也可以从
MainViewModel
中公开它的属性。公开其属性是“MVVM纯粹主义”方法,而公开整个模型有时更为实用


您的
MainViewModel
负责创建
DetailViewModels
的初始列表,并负责添加/删除这些项目。例如,在
MainViewModel.MainModel
属性的
PropertyChanged
事件中,它可能重建
MainViewModel.Details
集合,而
MainViewModel.Details
属性的
CollectionChanged
事件将更新
MainViewModel.MainModel.Details

以下是一个答案,我认为使用
observeviewmodelcollection

它又好又懒。它在ctor中使用ObservableCollection和ViewModelFactory。我喜欢它,因为它在它所属的模型层保持状态。GUI上的用户操作可以调用VM上的命令,这些命令通过M上的公共方法操纵M。在M层上产生的任何更改都将由该链接中的类自动处理


请注意我对SL与WPF的评论

我仍在制定解决方案,但我想在此指出一个大帮手:“重新填充MasterViewModel.Detail,每次更改MasterModel.Detail”奇怪的是,我没有想到这一点!我当然必须在初始化时构建它一次,这样我就可以随时重建将起作用,因为
m.Detail
是dif
public MasterViewModel(MasterModel m)
{
   _Model = m;
   _Detail = new ObservableCollection<DetailViewModel>(m.Detail);
}