wpf MVVM 模板的好例子
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1662309/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Good examples of MVVM Template
提问by jwarzech
I am currently working with the Microsoft MVVM template and find the lack of detailed examples frustrating. The included ContactBook example shows very little Command handling and the only other example I've found is from an MSDN Magazine article where the concepts are similar but uses a slightly different approach and still lack in any complexity. Are there any decent MVVM examples that at least show basic CRUD operations and dialog/content switching?
我目前正在使用 Microsoft MVVM 模板,但发现缺少详细示例令人沮丧。包含的 ContactBook 示例显示了很少的命令处理,我发现的唯一其他示例来自 MSDN 杂志文章,其中的概念相似,但使用的方法略有不同,并且仍然没有任何复杂性。是否有任何不错的 MVVM 示例至少显示基本的 CRUD 操作和对话框/内容切换?
Everyone's suggestions were really useful and I will start compiling a list of good resources
每个人的建议都非常有用,我将开始编制一份好的资源清单
Frameworks/Templates
框架/模板
Useful Articles
有用的文章
- WPF Apps With The Model-View-ViewModel Design Pattern
- Data Validation in .NET 3.5
- Using a ViewModel to Provide Meaningful Validation Error Messages
- Action based ViewModel and Model validation
- Dialogs
- Command Bindings in MVVM
- More than just MVC for WPF
- MVVM + Mediator Example Application
- 具有模型-视图-视图模型设计模式的 WPF 应用程序
- .NET 3.5 中的数据验证
- 使用 ViewModel 提供有意义的验证错误消息
- 基于动作的 ViewModel 和模型验证
- 对话框
- MVVM 中的命令绑定
- 不仅仅是 WPF 的 MVC
- MVVM + Mediator 示例应用程序
Screencasts
截屏视频
Additional Libraries
附加库
- WPF Disciples' improved Mediator Pattern implementation(I highly recommend this for applications that have more complex navigation)
- MVVM Light Toolkit Messenger
- WPF Disciples 改进的 Mediator Pattern 实现(对于具有更复杂导航的应用程序,我强烈建议这样做)
- MVVM Light Toolkit Messenger
采纳答案by Egor
Unfortunately there is no one great MVVM example app that does everything, and there are a lot of different approaches to doing things. First, you might want to get familiar with one of the app frameworks out there (Prism is a decent choice), because they provide you with convenient tools like dependency injection, commanding, event aggregation, etc to easily try out different patterns that suit you.
不幸的是,没有一个伟大的 MVVM 示例应用程序可以做所有事情,并且有很多不同的方法来做事情。首先,您可能想要熟悉其中一个应用程序框架(Prism 是一个不错的选择),因为它们为您提供了方便的工具,例如依赖项注入、命令、事件聚合等,可以轻松尝试适合您的不同模式.
The prism release:
http://www.codeplex.com/CompositeWPF
棱镜发布:http:
//www.codeplex.com/CompositeWPF
It includes a pretty decent example app (the stock trader) along with a lot of smaller examples and how to's. At the very least it's a good demonstration of several common sub-patterns people use to make MVVM actually work. They have examples for both CRUD and dialogs, I believe.
它包括一个相当不错的示例应用程序(股票交易者)以及许多较小的示例和操作方法。至少它很好地展示了人们用来使 MVVM 实际工作的几种常见子模式。我相信他们有 CRUD 和对话的例子。
Prism isn't necessarily for every project, but it's a good thing to get familiar with.
Prism 不一定适用于每个项目,但熟悉它是一件好事。
CRUD:This part is pretty easy, WPF two way bindings make it really easy to edit most data. The real trick is to provide a model that makes it easy to set up the UI. At the very least you want to make sure that your ViewModel (or business object) implements INotifyPropertyChanged
to support binding and you can bind properties straight to UI controls, but you may also want to implement IDataErrorInfo
for validation. Typically, if you use some sort of an ORM solution setting up CRUD is a snap.
CRUD:这部分非常简单,WPF 双向绑定使编辑大多数数据变得非常容易。真正的技巧是提供一个模型,使设置 UI 变得容易。至少您希望确保您的 ViewModel(或业务对象)实现INotifyPropertyChanged
支持绑定,并且您可以将属性直接绑定到 UI 控件,但您可能还希望实现IDataErrorInfo
以进行验证。通常,如果您使用某种 ORM 解决方案,则设置 CRUD 非常容易。
This article demonstrates simple crud operations: http://dotnetslackers.com/articles/wpf/WPFDataBindingWithLINQ.aspx
本文演示了简单的 crud 操作:http: //dotnetslackers.com/articles/wpf/WPFDataBindingWithLINQ.aspx
It is built on LinqToSql, but that is irrelevant to the example - all that is important is that your business objects implement INotifyPropertyChanged
(which classes generated by LinqToSql do). MVVM is not the point of that example, but I don't think it matters in this case.
它建立在 LinqToSql 之上,但这与示例无关 - 重要的是您的业务对象实现INotifyPropertyChanged
(由 LinqToSql 生成的类执行)。MVVM 不是那个例子的重点,但我认为在这种情况下它并不重要。
This article demonstrates data validation
http://blogs.msdn.com/wpfsdk/archive/2007/10/02/data-validation-in-3-5.aspx
本文演示数据验证
http://blogs.msdn.com/wpfsdk/archive/2007/10/02/data-validation-in-3-5.aspx
Again, most ORM solutions generate classes that already implement IDataErrorInfo
and typically provide a mechanism to make it easy to add custom validation rules.
同样,大多数 ORM 解决方案生成的类已经实现,IDataErrorInfo
并且通常提供一种机制来轻松添加自定义验证规则。
Most of the time you can take an object(model) created by some ORM and wrap it in a ViewModel that holds it and commands for save/delete - and you're ready to bind UI straight to the model's properties.
大多数情况下,您可以获取由某个 ORM 创建的对象(模型)并将其包装在一个 ViewModel 中,该模型包含它和保存/删除命令 - 您已经准备好将 UI 直接绑定到模型的属性。
The view would look like something like this (ViewModel has a property Item
that holds the model, like a class created in the ORM):
视图看起来像这样(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>
Dialogs:Dialogs and MVVM are a bit tricky. I prefer to use a flavor of the Mediator approach with dialogs, you can read a little more about it in this StackOverflow question:
WPF MVVM dialog example
对话框:对话框和 MVVM 有点棘手。我更喜欢在对话框中使用 Mediator 方法的风格,您可以在这个 StackOverflow 问题中阅读更多关于它的信息:
WPF MVVM 对话框示例
My usual approach, which is not quite classic MVVM, can be summarized as follows:
我常用的方法,不是很经典的MVVM,可以总结如下:
A base class for a dialog ViewModel that exposes commands for commit and cancel actions, an event to lets the view know that a dialog is ready to be closed, and whatever else you will need in all of your dialogs.
对话框 ViewModel 的基类,用于公开提交和取消操作的命令,让视图知道对话框已准备好关闭的事件,以及您在所有对话框中需要的任何其他内容。
A generic view for your dialog - this can be a window, or a custom "modal" overlay type control. At its heart it is a content presenter that we dump the viewmodel into, and it handles the wiring for closing the window - for example on data context change you can check if the new ViewModel is inherited from your base class, and if it is, subscribe to the relevant close event (the handler will assign the dialog result). If you provide alternative universal close functionality (the X button, for instance), you should make sure to run the relevant close command on the ViewModel as well.
对话框的通用视图 - 这可以是一个窗口,也可以是一个自定义的“模态”覆盖类型控件。从本质上讲,它是一个内容展示器,我们将视图模型转储到其中,它处理关闭窗口的连接 - 例如,在数据上下文更改时,您可以检查新的 ViewModel 是否从您的基类继承,如果是,订阅相关的关闭事件(处理程序将分配对话结果)。如果您提供替代的通用关闭功能(例如 X 按钮),您应该确保也在 ViewModel 上运行相关的关闭命令。
Somewhere you need to provide data templates for your ViewModels, they can be very simple especially since you probably have a view for each dialog encapsulated in a separate control. The default data template for a ViewModel would then look something like this:
在需要为 ViewModel 提供数据模板的地方,它们可以非常简单,特别是因为您可能将每个对话框的视图封装在单独的控件中。ViewModel 的默认数据模板将如下所示:
<DataTemplate DataType="{x:Type vmodels:AddressEditViewModel}">
<views:AddressEditView DataContext="{Binding}" />
</DataTemplate>
The dialog view needs to have access to these, because otherwise it won't know how to show the ViewModel, aside from the shared dialog UI its contents are basically this:
对话框视图需要访问这些,否则它不知道如何显示 ViewModel,除了共享对话框 UI 之外,它的内容基本上是这样的:
<ContentControl Content="{Binding}" />
The implicit data template will map the view to the model, but who launches it?
隐式数据模板会将视图映射到模型,但谁启动它?
This is the not-so-mvvm part. One way to do it is to use a global event. What I think is a better thing to do is to use an event aggregator type setup, provided through dependency injection - this way the event is global to a container, not the whole app. Prism uses the unity framework for container semantics and dependency injection, and overall I like Unity quite a bit.
这是不那么 mvvm 的部分。一种方法是使用全局事件。我认为更好的做法是使用通过依赖注入提供的事件聚合器类型设置 - 这样事件对容器是全局的,而不是整个应用程序。Prism 使用 Unity 框架进行容器语义和依赖注入,总体而言我非常喜欢 Unity。
Usually, it makes sense for the root window to subscribe to this event - it can open the dialog and set its data context to the ViewModel that gets passed in with a raised event.
通常,根窗口订阅此事件是有意义的 - 它可以打开对话框并将其数据上下文设置为通过引发的事件传入的 ViewModel。
Setting this up in this way lets ViewModels ask the application to open a dialog and respond to user actions there without knowing anything about the UI so for the most part the MVVM-ness remains complete.
以这种方式进行设置后,ViewModel 可以要求应用程序打开一个对话框并在那里响应用户操作,而无需了解有关 UI 的任何信息,因此在大多数情况下,MVVM 特性仍然完整。
There are times, however, where the UI has to raise the dialogs, which can make things a bit trickier. Consider for example, if the dialog position depends on the location of the button that opens it. In this case you need to have some UI specific info when you request a dialog open. I generally create a separate class that holds a ViewModel and some relevant UI info. Unfortunately some coupling seems unavoidable there.
然而,有时 UI 必须提高对话框,这会使事情变得有点棘手。例如,考虑对话框位置是否取决于打开它的按钮的位置。在这种情况下,当您请求打开对话框时,您需要一些特定于 UI 的信息。我通常会创建一个单独的类来保存 ViewModel 和一些相关的 UI 信息。不幸的是,有些耦合似乎是不可避免的。
Pseudo code of a button handler that raises a dialog which needs element position data:
引发需要元素位置数据的对话框的按钮处理程序的伪代码:
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
}
The dialog view will bind to position data, and pass the contained ViewModel to the inner ContentControl
. The ViewModel itself still doesn't know anything about the UI.
对话框视图将绑定到位置数据,并将包含的 ViewModel 传递给内部ContentControl
. ViewModel 本身仍然对 UI 一无所知。
In general I don't make use of the DialogResult
return property of the ShowDialog()
method or expect the thread to block until the dialog is closed. A non-standard modal dialog doesn't always work like that, and in a composite environment you often don't really want an event handler to block like that anyhow. I prefer to let the ViewModels deal with this - the creator of a ViewModel can subscribe to its relevant events, set commit/cancel methods, etc, so there is no need to rely on this UI mechanism.
一般来说,我不会使用DialogResult
该ShowDialog()
方法的返回属性,也不会期望线程在对话框关闭之前阻塞。非标准模态对话框并不总是这样工作,在复合环境中,您通常不希望事件处理程序以任何方式阻塞。我更喜欢让 ViewModels 来处理这个 - ViewModel 的创建者可以订阅它的相关事件,设置提交/取消方法等,所以不需要依赖这个 UI 机制。
So instead of this flow:
所以,而不是这个流程:
// in code behind
var result = somedialog.ShowDialog();
if (result == ...
I use:
我用:
// 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
I prefer it this way because most of my dialogs are non-blocking pseudo-modal controls and doing it this way seems more straightforward than working around it. Easy to unit test as well.
我更喜欢这种方式,因为我的大多数对话框都是非阻塞的伪模态控件,而且这样做似乎比解决它更简单。也易于单元测试。
回答by nportelli
Jason Dolinger made a good screencastof MVVM. Like Egor mentioned there is no one good example. They are all over. Most are good MVVM examples, but not when you get into complex issues. Everyone has their own way. Laurent Bugnion has a good way to communicate between viewmodels as well. http://blog.galasoft.ch/archive/2009/09/27/mvvm-light-toolkit-messenger-v2-beta.aspxCinch is also a good example. Paul Stovel has a good postthat explains a lot too with his Magellan framework.
Jason Dolinger 制作了一个很好的 MVVM截屏视频。就像叶戈尔提到的那样,没有一个很好的例子。他们都结束了。大多数都是很好的 MVVM 示例,但在遇到复杂问题时则不然。每个人都有自己的方式。Laurent Bugnion 也有一种在视图模型之间进行通信的好方法。 http://blog.galasoft.ch/archive/2009/09/27/mvvm-light-toolkit-messenger-v2-beta.aspxCinch 也是一个很好的例子。Paul Stovel 有一篇很好的帖子,用他的麦哲伦框架也解释了很多。
回答by McBainUK
Found this one useful. Has code too.
发现这个很有用。也有代码。
回答by Shivam Srivastava
Here I am adding link of a WPF(Inventory Management App) applicationwhich using MVVM architecturedesigned by me .
在这里,我添加了使用 我设计的MVVM 架构的WPF(库存管理应用程序)应用程序的链接。
Its UI is awesome. https://github.com/shivam01990/InventoryManagement
它的用户界面很棒。 https://github.com/shivam01990/InventoryManagement
回答by Andy S
回答by Scott Whitlock
I also shared in your frustration. I'm writing an application and I had these 3 requirements:
我也分担了你的沮丧。我正在编写一个应用程序,我有以下 3 个要求:
- Extensible
- WPF with MVVM
- GPL compatible examples
- 可扩展
- 带有 MVVM 的 WPF
- GPL 兼容示例
All I found were bits and pieces, so I just started writing it the best I could. After I got into it a bit, I realized there might be other people (like yourself) who could use a reference application, so I refactored the generic stuff out into a WPF/MVVM application framework and released it under the LGPL. I named it SoapBox Core. If you go to the downloads page, you'll see it comes with a small demo application, and the source code for that demo application is also available for download. Hope you find that helpful. Also, email me at scott {at} soapboxautomation.com if you want more info.
我发现的只是点点滴滴,所以我开始尽我所能地写它。在深入了解之后,我意识到可能还有其他人(比如您自己)可以使用参考应用程序,因此我将通用内容重构为 WPF/MVVM 应用程序框架,并在 LGPL 下发布。我将其命名为SoapBox Core。如果您转到下载页面,您会看到它带有一个小型演示应用程序,并且该演示应用程序的源代码也可供下载。希望你觉得这有帮助。另外,如果您想了解更多信息,请通过 scott {at} soapboxautomation.com 给我发电子邮件。
EDIT: Also posted a CodeProject articleexplaining how it works.
编辑:还发布了一篇 CodeProject 文章,解释了它是如何工作的。
回答by Reed Copsey
The sample project in the Cinch frameworkshows basic CRUD and navigation tools. It's a fairly good example of using MVVM, and includes a multi-part articleexplaining its usage and motivations.
Cinch 框架中的示例项目显示了基本的 CRUD 和导航工具。这是使用 MVVM 的一个很好的例子,包括一篇解释其用法和动机的多部分文章。
回答by Shivprasad Ktheitroadala
I have written a simple MVVM example from scratch on code project here is the link MVVM WPF step by step. It starts from a simple 3 layer architecture and graduates you to use some framework like PRISM.
我在代码项目上从头开始编写了一个简单的 MVVM 示例,这里是一步一步的链接MVVM WPF。它从一个简单的 3 层架构开始,然后让您使用一些框架,如 PRISM。
回答by Abdulsattar Mohammed
Even I shared the frustration until I took the matter into my hands. I started IncEditor.
甚至我也分担了沮丧,直到我将此事掌握在自己手中。我启动了 IncEditor。
IncEditor (http://inceditor.codeplex.com) is an editor that tries to introduce developers to WPF, MVVM & MEF. I started it and managed to get some functionality like 'theme' support. I am no expert in WPF or MVVM or MEF so I can't put a lot of functionality in it. I make a sincere request to you guys to make it better so that nutters like me can understand it better.
IncEditor ( http://inceditor.codeplex.com) 是一个试图向开发人员介绍 WPF、MVVM 和 MEF 的编辑器。我启动了它并设法获得了一些功能,例如“主题”支持。我不是 WPF 或 MVVM 或 MEF 方面的专家,所以我不能在其中加入很多功能。真诚的请求你们把它做得更好,让像我这样的疯子能更好地理解它。