MVVM毫无意义?
是正统的MVVM实现没有意义? 我正在创build一个新的应用程序,我认为Windows窗体和WPF。 我selectWPF是因为它具有前瞻性,并提供了很大的灵活性。 代码更less,使用XAML可以更轻松地对UI进行重大更改。
由于WPF的select是显而易见的,我认为我可以将MVVM作为我的应用程序体系结构,因为它提供了可混合性,分离性和单元可testing性。 理论上,UI编程的圣杯似乎很漂亮。 这个简短的冒险 然而,变成了一个真正的头痛。 正如我们在实践中预期的那样,我发现我已经为另一个交易了一个问题。 我倾向于成为一名执着的程序员,因为我想以正确的方式做事情,以便得到正确的结果,并有可能成为更好的程序员。 MVVM模式刚刚在我的生产力testing中失败了,刚刚变成了一个很大的黑客!
清楚的例子是添加对模式对话框的支持。 正确的方法是build立一个对话框并将其绑定到视图模型。 让这个工作很困难。 为了从MVVM模式中受益,必须在应用程序的各个层次的几个地方分发代码。 您还必须使用深奥的编程结构,如模板和lambaexpression式。 东西,让你盯着屏幕抓挠你的头。 这使得维护和debugging成为我最近发现的等待发生的噩梦。 我有一个关于盒子工作正常,直到我第二次调用它时,我得到一个exception,说它一旦closures它不能再次显示对话框。 我不得不添加一个closuresfunction的事件处理程序到对话框窗口,另外一个在IDialogView实现中,最后在IDialogViewModel中添加另一个。 我以为MVVM会把我们从这种奢侈的黑客中拯救出来!
有几个人在那里与这个问题竞争的解决scheme,他们都是黑客,并没有提供一个干净,容易重用,优雅的解决scheme。 大部分MVVM工具包都会遮盖对话框,并且当它们处理它们时,它们只是不需要自定义界面或视图模型的警报框。
我打算放弃MVVM视图模式,至less是正统的实现。 你怎么看? 如果您有任何问题,是否值得您麻烦? 我只是一个无能的程序员,或者MVVM不是它被夸大了吗?
对不起,如果我的答案变得有点长,但不要怪我! 你的问题也很长。
总之,MVVM并不是毫无意义的。
清楚的例子是添加对模式对话框的支持。 正确的方法是build立一个对话框并将其绑定到视图模型。 让这个工作很困难。
是的,它确实是。
但是,MVVM为您提供了将UI的外观与其逻辑分开的方法。 没有人强迫你在任何地方使用它,没有人拿着枪对着你的额头,让你创build一个单独的ViewModel的一切。
这是我为这个特定的例子的解决scheme:
用户界面如何处理特定的input不是ViewModel的业务。 我会将代码添加到View的.xaml.cs文件中,该文件实例化对话框,并将其设置为其DataContext相同的ViewModel实例(如果需要的话)。
为了从MVVM模式中受益,您必须在应用程序的各个层次的几个地方分发代码。 您还必须使用深奥的编程结构,如模板和lambaexpression式。
那么,你不必在几个地方使用它。 这是我将如何解决它:
- 将XAML添加到视图中,而不是.xaml.cs中的任何内容
- 在ViewModel中编写每个应用程序的逻辑(除了直接使用UI元素操作的东西)
- 所有应该由UI完成但与业务逻辑无关的代码进入.xaml.cs文件
我认为MVVM的目的主要是将应用程序的逻辑和具体的UI分离开来,因此可以轻松修改(或完全replace)UI。
我使用以下原则:View可以从ViewModel中知道并假设它想要的任何东西,但是ViewModel可以不了解View。
WPF提供了一个很好的绑定模型,你可以用它来实现。
(顺便说一下,如果使用正确的话,模板和lambdaexpression式并不是很深奥,但是如果你不想,就不要使用它们。)
东西,让你盯着屏幕抓挠你的头。
是的,我知道这种感觉。 当我第一次看到MVVM的时候,我确实感觉到了什么。 但一旦掌握了它,它就不会再感觉不好了。
我有一个约盒子工作正常…
你为什么要把一个ViewModel放在一个大框里面? 这点没有意义。
大部分MVVM工具包都会遮盖对话框,并且当它们处理它们时,它们只是不需要自定义界面或视图模型的警报框。
是的,因为UI元素在同一个窗口或另一个窗口中,或者正在轨道运行火星的事实不是ViewModel的关注。
关注点分离
编辑:
这是一个非常好的video,其标题是构build自己的MVVM框架 。 值得一看。
让这个工作很困难。 为了从MVVM模式中受益,您必须在应用程序的各个层次的几个地方分发代码。 您还必须使用深奥的编程结构,如模板和lambaexpression式。
对于一个普通的模式对话框? 你当然在那里做错了什么 – MVVM的实现不必那么复杂。
考虑到你对MVVM和WPF都是新手,很可能你正在使用次优解决scheme,并且不必要地使事情复杂化 – 至less我第一次去WPF的时候是这么做的。 确保问题真的是MVVM,而不是放弃之前的实现。
MVVM,MVC,文档视图等是一个古老的模式家族。有缺点,但没有你描述的那种致命的缺陷。
我通过作弊来处理对话问题。 我的MainWindow实现了一个IWindowServices接口,它公开了所有特定于应用程序的对话框。 然后我的其他ViewModels可以导入服务接口(我使用MEF,但你可以轻松地通过构造函数手动传递接口),并使用它来完成必要的。 例如,下面是我的一个小实用程序应用程序界面的样子:
//Wrapper interface for dialog functionality to allow for mocking during tests public interface IWindowServices { bool ExecuteNewProject(NewProjectViewModel model); bool ExecuteImportSymbols(ImportSymbolsViewModel model); bool ExecuteOpenDialog(OpenFileDialog dialog); bool ExecuteSaveDialog(SaveFileDialog dialog); bool ExecuteWarningConfirmation(string text, string caption); void ExitApplication(); }
这将所有的对话执行放在一个地方,它可以很容易被剔除出unit testing。 我遵循对话框的客户端必须创build适当的ViewModel的模式,然后可以根据需要进行configuration。 执行调用块,然后客户端可以查看ViewModel的内容来查看对话框结果。
一个更“纯粹”的MVVMdevise对于一个需要更清洁绝缘和更复杂组合的大型应用程序来说可能是重要的,但是对于中小型应用程序,我认为一个实用的方法,通过适当的服务来揭示所需的钩子是足够的。
devise模式可以帮助你,而不是阻碍。 作为一名优秀开发人员的一小部分是知道何时“违反规则”。 如果MVVM对于一项任务来说很麻烦,而且你确定未来的价值不值得付出努力,那么就不要使用这个模式。 例如,正如其他海报所评论的那样,为什么要通过所有的开销来实现一个简单的框?
devise模式从未打算被教条式地遵循。
我正在使用PRISM进行一个非常复杂的MVVM开发,所以我已经不得不应对这种担忧了。
我个人的结论是:
MVVM vs MVC / PopUps&co
- MVVM真的是一个很好的模式,在大多数情况下,它完全取代了MVC,这要归功于WPF中强大的数据绑定
- 在大多数情况下直接从演示者调用服务层是合法的实现
- 即使相当复杂的List / Detail场景也可以由纯MVVM实现,这要归功于{Binding Path = /}语法
- 但是,当需要实施多个视图之间的复杂协调时,控制器是强制的
- 可以使用事件; 这意味着在控制器中存储IView(或AbstractObserver)实例的旧模式已经过时
- 控制器可以通过IOC容器注入到每个Presenter中
- Prism的IEventAggregator服务是另一种可能的解决scheme,如果控制器的唯一用途是事件派发(在这种情况下,它可以完全替代控制器)
- 如果视图是dynamic创build的,这对于控制器来说是非常合适的工作(在prism中,控制器将被注入(IOC)IRegionManager)
- 现代组合应用程序中的modal dialog大多已经过时,除了真正的阻止操作,如强制确认; 在这些情况下,模态激活可以被抽象为在控制器内部调用的服务,并且由专门的类来实现,这也允许进行高级的表示级unit testing。 例如,控制器将调用IConfirmationService.RequestConfirmation(“你确定”),这将在运行时触发一个modal dialog显示,并可以在unit testing过程中轻松地模拟
由于模式本身MVVM是伟大的。 但是WPF的.NET 4.0数据绑定支持的控件库非常有限,比WinForm好很多,但是对于可绑定的MVVM还是不够的,我认为它的功耗约为可绑定MVVM的30%。
可绑定的MVVM:它是ViewModel与View仅通过数据绑定连接的UI。
MVVM模式是关于ViewState的对象表示,它没有描述如何保持View和ViewModel之间的同步,在WPF中它是数据绑定的,但它可以是任何东西。 实际上,你可以在任何支持事件\callback的UI工具箱中使用MVVM模式,你可以在WinForms中使用它纯WinAPI(我做过,而且事件\callback没有更多的工作),你甚至可以在文本中使用它控制台,就像使用MVVM模式重写DoS的Norton Commander一样。
简而言之:MVVM不是没有意义的,这很棒。 NET 4.0 WPF的控制库是垃圾。
这里是ViewModel概念的简单certificate,你不能使用WPF以纯MVVM方式绑定数据。
public class PersonsViewModel { public IList<Person> PersonList; public IList<ColumnDescription> TableColumns; public IList<Person> SelectedPersons; public Person ActivePerson; public ColumnDescription SortedColumn; }
你不能绑定WPF的DataGrid列标题,你不能绑定选定的行等数据,你可以用代码简单的方法来做,也可以为这5行最简单的ViewModel编写200行的XAML hack代码。 你只能想象复杂的ViewModel如何让事情变得更加糟糕。
所以答案是simmple,除非你正在编写Hello World应用程序,在WPF中使用可绑定的MVVM是毫无意义的。 你将花大部分时间思考黑客绑定你ViewModel。 数据绑定是好的,但准备回落到事件的70%的时间。
当涉及(模态)对话框时,我已经看到了与MVVM实现相同的问题。 当我看到MVVM模式的参与者时,我觉得缺less构build连贯应用程序的东西。
- View包含特定的GUI控件,并定义用户界面的外观。
- ViewModel表示演示文稿的状态和行为。
- 模型可以是来自域层或提供必要数据的服务的业务对象。
但缺失的是:
- 谁创buildViewModels?
- 谁负责应用程序工作stream程?
- 当ViewModel需要彼此沟通时,谁进行调解?
我的方法是引入一个(用例) 控制器 ,负责丢失的点。 在WPF应用程序框架(WAF)示例应用程序中可以看到如何工作。
不,这不是毫无意义的,但即使模式本身简单可笑,也很难将其包裹起来。 那里有大量的错误信息和各种正确的战斗。 我认为,使用WPF和Silverlight你应该使用MVVM,否则你将会过度编码,并尝试用新的模式解决问题,这种“老式”的胜利forms方法会导致你陷入困境。 这在Silverlight中更是如此,因为要求所有东西都是asynchronous的(围绕这一点是可能的,但你应该select另一个平台)。
我build议阅读本文通过仔细使用ViewModel模式来简化WPF TreeView,了解MVVM如何很好地实现,并允许您将胜利forms的思路改变为MVVM中的新思维方式。 简而言之,当你想完成某些事情时,首先将逻辑应用于ViewModel而不是View。 你想select一个项目? 更改图标? 不要迭代UI元素,只需更新模型属性并让数据绑定完成这些工作。