MVVM模板的好例子
我目前正在使用Microsoft MVVM模板,并发现缺乏令人沮丧的详细示例。 包含的ContactBook示例显示的命令处理非常少,我发现的另一个示例来自MSDN Magazine文章,其中的概念相似,但使用稍微不同的方法,但仍缺乏复杂性。 是否有任何体面的MVVM示例至少显示了基本的CRUD操作和对话/内容切换?
每个人的建议都非常有用,我将开始编写一份好的资源清单
框架/模板
有用的文章
截屏
其他库
不幸的是,没有一个伟大的MVVM示例应用程序能够完成所有工作,而且还有很多不同的方法来完成任务。 首先,您可能想熟悉一个应用程序框架(Prism是一个不错的选择),因为它们为您提供诸如依赖注入,命令,事件聚合等方便的工具,以轻松地尝试适合您的不同模式。
棱镜发布:
http://www.codeplex.com/CompositeWPF
它包括一个相当不错的示例应用程序(股票交易员)以及许多较小的示例以及如何操作。 至少这是人们用MVVM实际工作的几个常见子模式的一个很好的例子。 我相信他们都有CRUD和对话的例子。
棱镜并不一定适用于所有项目,但熟悉这一点是件好事。
CRUD:这一部分非常简单,WPF双向绑定使编辑大多数数据变得非常简单。 真正的窍门是提供一个模型,可以很容易地设置UI。 至少要确保ViewModel(或业务对象)实现INotifyPropertyChanged
以支持绑定,并且可以将属性直接绑定到UI控件,但是您可能还需要实现IDataErrorInfo
进行验证。 通常情况下,如果您使用某种ORM解决方案,那么设置CRUD是很简单的。
本文演示简单的crud操作:http://dotnetslackers.com/articles/wpf/WPFDataBindingWithLINQ.aspx
它基于LinqToSql构建,但与示例无关 - 重要的是您的业务对象实现INotifyPropertyChanged
(由LinqToSql生成的哪些类)。 MVVM不是这个例子的要点,但我认为这并不重要。
本文演示数据验证
http://blogs.msdn.com/wpfsdk/archive/2007/10/02/data-validation-in-3-5.aspx
同样,大多数ORM解决方案生成的类已经实现了IDataErrorInfo
并且通常提供了一种机制来使添加自定义验证规则变得容易。
大多数情况下,您可以将由某个ORM创建的对象(模型)包装到ViewModel中,该ViewModel包含它以及用于保存/删除的命令 - 并且您已准备好将UI直接绑定到模型的属性。
视图看起来像这样(ViewModel有一个属性Item
来存放模型,就像在ORM中创建的类一样):
<StackPanel>
<StackPanel DataContext=Item>
<TextBox Text="{Binding FirstName, Mode=TwoWay, ValidatesOnDataErrors=True}" />
<TextBox Text="{Binding LastName, Mode=TwoWay, ValidatesOnDataErrors=True}" />
</StackPanel>
<Button Command="{Binding SaveCommand}" />
<Button Command="{Binding CancelCommand}" />
</StackPanel>
对话框:对话框和MVVM有点棘手。 我更喜欢在对话框中使用Mediator方法,您可以在这个StackOverflow问题中阅读更多关于它的内容:
WPF MVVM对话框示例
我常用的方法,不是很经典的MVVM,可以概括如下:
一个对话框ViewModel的基类,它提供了提交和取消操作的命令,让视图知道对话已准备好关闭的事件,以及在所有对话中需要的任何其他操作。
对话框的通用视图 - 可以是窗口,也可以是自定义“模式”叠加类型控件。 它的核心是一个内容展示者,我们将视图模型转储到其中,并处理关闭窗口的布线 - 例如,在数据上下文更改时,您可以检查新ViewModel是否从您的基类继承,如果是,订阅相关的关闭事件(处理程序将分配对话结果)。 如果您提供备用通用关闭功能(例如X按钮),则应确保在ViewModel上也运行相关的关闭命令。
某处需要为ViewModel提供数据模板,因为它们可能非常简单,特别是因为您可能为每个对话框封装了一个单独的控件。 ViewModel的默认数据模板将如下所示:
<DataTemplate DataType="{x:Type vmodels:AddressEditViewModel}>
<views:AddressEditView DataContext={Binding} />
</DataTemplate>
对话框视图需要访问这些对象,否则它不知道如何显示ViewModel,除了共享对话框UI之外,其内容基本上是这样的:
<ContentControl Content={Binding} />
隐式数据模板将视图映射到模型,但是谁启动它?
这不是mvvm的一部分。 一种方法是使用全局事件。 我认为更好的做法是使用通过依赖注入提供的事件聚合器类型设置 - 通过这种方式,事件对于容器是全局的,而不是整个应用程序。 Prism使用统一框架来进行容器语义和依赖注入,总的来说,我非常喜欢Unity。
通常情况下,根窗口订阅此事件是有意义的 - 它可以打开对话框并将其数据上下文设置为ViewModel,该ViewModel通过引发事件传入。
通过这种方式进行设置,ViewModel可以让应用程序打开一个对话框,并在不知道UI的情况下响应用户的操作,因此大多数情况下MVVM内核仍然完整。
然而,有时候UI需要提高对话框,这会让事情变得更加棘手。 例如,考虑对话框的位置取决于打开它的按钮的位置。 在这种情况下,当您请求打开对话框时,您需要获得一些特定于用户界面的信息。 我通常创建一个独立的类,它包含一个ViewModel和一些相关的UI信息。 不幸的是,有些耦合在那里似乎不可避免。
引发需要元素位置数据的对话框的按钮处理函数的伪代码:
ButtonClickHandler(sender, args){
var vm = DataContext as ISomeDialogProvider; // check for null
var ui_vm = new ViewModelContainer();
// assign margin, width, or anything else that your custom dialog might require
...
ui_vm.ViewModel = vm.SomeDialogViewModel; // or .GetSomeDialogViewModel()
// raise the dialog show event
}
对话视图将绑定到位置数据,并将包含的ViewModel传递给内部ContentControl
。 ViewModel本身仍然不知道UI的任何内容。
一般来说,我不会使用ShowDialog()
方法的DialogResult
return属性,也不希望线程阻塞,直到关闭对话框。 非标准的模式对话框并不总是这样工作,而在复合环境中,您通常不希望事件处理程序像这样阻止。 我更喜欢让ViewModel处理这个问题 - ViewModel的创建者可以订阅其相关事件,设置提交/取消方法等,因此不需要依赖此UI机制。
所以,而不是这个流程:
// in code behind
var result = somedialog.ShowDialog();
if (result == ...
我用:
// in view model
var vm = new SomeDialogViewModel(); // child view model
vm.CommitAction = delegate { this.DoSomething(vm); } // what happens on commit
vm.CancelAction = delegate { this.DoNothing(vm); } // what happens on cancel/close (optional)
// raise dialog request event on the container
我更喜欢这种方式,因为我的大多数对话框都是非阻塞的伪模式控件,这样做似乎比解决它更直接。 易于进行单元测试。
Jason Dolinger制作了一个MVVM的好屏幕录像。 像叶戈尔提到的那样,没有一个好例子。 他们都结束了。 大多数都是很好的MVVM示例,但当您遇到复杂问题时不会。 每个人都有自己的方式。 Laurent Bugnion也有一种很好的方法来在视图模型之间进行交流。 http://blog.galasoft.ch/archive/2009/09/27/mvvm-light-toolkit-messenger-v2-beta.aspx Cinch也是一个很好的例子。 Paul Stovel有一篇很好的文章,他的麦哲伦框架也解释了很多。
你看过Caliburn吗? ContactManager示例有很多好东西。 通用的WPF示例还提供了一个很好的命令概述。 文档相当不错,论坛也很活跃。 推荐的!
链接地址: http://www.djcxy.com/p/20277.html