正统的MVVM实现是否毫无意义?我正在创建一个新的应用程序,我考虑了Windows窗体和WPF。我之所以选择WPF,是因为它具有前瞻性,并提供了很大的灵活性。使用XAML的代码更少,更容易对UI进行重大更改。
由于WPF的选择是显而易见的,我认为我可以使用MVVM作为我的应用程序架构,因为它提供了可混合性,分离问题和单元可测试性。从理论上讲,它看起来很像UI编程的圣杯。这个简短的冒险;然而,已经变成了一个真正的头痛。 正如在实践中所预期的那样,我发现我已将一个问题换成了另一个问题。我倾向于成为一个强迫性的程序员,因为我想以正确的方式做事,这样我才能获得正确的结果,并可能成为更好的程序员。 MVVM模式刚刚结束了我对生产力的测试,刚刚变成了一个令人讨厌的大黑客!
明显的例子是添加对模态对话框的支持。正确的方法是建立一个对话框并将其绑定到视图模型。让这个工作很难。为了从MVVM模式中受益,您必须在应用程序的各个层中的多个位置分发代码。您还必须使用深奥的编程结构,如模板和lamba表达式。让你盯着屏幕挠挠头的东西。正如我最近发现的那样,这使得维护和调试成为一场噩梦。我有一个关于盒子的工作正常,直到我第二次调用它时出现异常,说它一旦关闭就无法再显示对话框。我必须为对话框窗口添加一个关闭功能的事件处理程序,在IDialogView实现中添加另一个,最后在IDialogViewModel中添加另一个。我以为MVVM会让我们免于这种奢侈的骚扰!
有几个人在这个问题上有竞争解决方案,他们都是黑客,并没有提供一个干净,易于重复使用的优雅解决方案。大多数MVVM工具包都会掩盖对话框,当它们确实解决它们时,它们只是不需要自定义接口或视图模型的警报框。
我打算放弃MVVM视图模式,至少是它的正统实现。你怎么看?如果你有任何问题,是否值得为你带来麻烦?我只是一个不称职的程序员,还是MVVM而不是它被宣传的内容?
答案 0 :(得分:59)
很抱歉,如果我的答案变得有点长,但不要怪我!你的问题也很冗长。
总之,MVVM并非毫无意义。
明显的例子是增加 支持模态对话框。该 正确的方法是建立一个对话框 并将其绑定到视图模型。入门 这项工作很难。
是的,确实如此 但是,MVVM为您提供了一种将UI外观与逻辑分离的方法。没有人强迫你到处使用它,没有人拿着枪对着你的额头,让你为一切创建一个单独的ViewModel。
以下是我对此特定示例的解决方案:
UI如何处理某个输入不是ViewModel的业务。我会将代码添加到View的.xaml.cs文件中,该文件实例化对话框并将相同的ViewModel实例(或其他东西,如果需要)设置为其DataContext。
为了从MVVM模式中受益,您必须在应用程序的各个层中的多个位置分发代码。您还必须使用深奥的编程结构,如模板和lamba表达式。
好吧,你不必在几个地方使用它。这就是我要解决的问题:
我认为MVVM的目的主要是分离应用程序的逻辑和具体的UI,从而实现UI的轻松修改(或完全替换)。
我使用以下原则:View可以从ViewModel知道并假设它想要的任何内容,但ViewModel可以知道关于视图的任何内容。
WPF提供了一个很好的绑定模型,您可以使用它来实现这一目标。
(顺便说一句,如果使用得当,模板和lambda表达式并不深奥。但如果你不想这样做,请不要使用它们。)
是的,我知道这种感觉。正是我第一次看到MVVM时的感受。但是一旦掌握了它,就不会再感觉不好了。让你盯着屏幕挠挠头的东西。
我的盒子工作得很好......
为什么要将ViewModel放在about box后面?没有意义。
大多数MVVM工具包都会掩盖对话框,当它们确实解决它们时,它们只是不需要自定义界面或视图模型的警告框。
是的,因为UI元素位于同一个窗口或另一个窗口,或者目前正在围绕火星运行的事实不是ViewModels关注的问题。
Separation of Concerns
修改强>
这是一个非常好的视频,其标题是Build your own MVVM framework。值得一看。
答案 1 :(得分:8)
让这个工作变得困难。在 为了从MVVM中受益 模式,你必须分发代码 在整个地方的几个地方 你的申请层。你也是 必须使用深奥的编程 构造像模板和lamba 表达式。
对于普通的模态对话框?你肯定在那里做错了 - MVVM实现不一定非常复杂。
考虑到你对MVVM和WPF都不熟悉,很可能你到处都使用次优解决方案并且不必要地使事情变得复杂 - 至少我在第一次使用WPF时这样做了。放弃之前,确保问题确实是MVVM,而不是你的实现。
答案 2 :(得分:5)
我通过作弊处理对话问题。我的MainWindow实现了一个IWindowServices接口,该接口公开了所有特定于应用程序的对话框。然后我的其他ViewModel可以导入服务接口(我使用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();
}
这会将所有Dialog执行放在一个位置,并且可以很容易地将其删除以进行单元测试。我遵循对话框的客户端必须创建适当的ViewModel的模式,然后他们可以根据需要进行配置。执行调用块,然后客户端可以查看ViewModel的内容以查看Dialog结果。
更“纯粹”的MVVM设计对于大型应用程序可能很重要,在这种应用程序中,您需要更清洁的绝缘和更复杂的组合,但对于中小型应用程序,我认为这是一种实用的方法,通过适当的服务来暴露所需的钩子,已经足够了。
答案 3 :(得分:5)
我正在使用PRISM进行相当复杂的MVVM开发,因此我已经不得不应对这种担忧。
我的个人结论:
MVVM vs MVC / PopUps&共
答案 4 :(得分:5)
设计模式可以帮助您,而不是阻碍。成为优秀开发人员的一小部分是知道何时“违反规则”。如果MVVM对于任务来说很麻烦,并且您已确定未来的值不值得付出努力,那么请不要使用该模式。例如,正如其他海报所评论的那样,为什么要通过所有开销来实现一个简单的框?
设计模式从未被教条化。
答案 5 :(得分:1)
由于模式本身MVVM很棒。但WPF的控件库附带的.NET 4.0数据绑定支持是非常有限的,它比WinForm好很多,但对于可绑定的MVVM来说仍然不够,我想它的功率大约是可绑定MVVM所需的30%。登记/> 可绑定MVVM:它是ViewModel仅使用数据绑定与View连接的UI MVVM模式是关于ViewState的对象表示,它没有描述如何维护View和ViewModel之间的同步,在WPF中它的数据绑定却可以是任何东西。实际上你可以在支持事件\回调的任何UI工具包中使用MVVM模式,你可以在WinForms的纯WinAPI中使用它(我做过,而且事件\回调没有太多工作),你甚至可以在文本中使用它控制台,就像使用MVVM模式重写DoS的Norton Commander一样。
简而言之:MVVM并非毫无意义,它很棒。 NET 4.0 WPF的控件库是垃圾。
以下是ViewModel的简单概念证明,您无法使用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行写一个200行的XAML黑客代码最简单的ViewModel。你只能想象复杂的ViewModel会让事情变得更糟 所以答案是简单的,除非您正在编写Hello World应用程序,在WPF中使用可绑定MVVM是没有意义的。您将花费大部分时间考虑hack绑定ViewModel。数据绑定很不错,但准备回退到事件的70%时间。
答案 6 :(得分:0)
不,这并非毫无意义,但即使模式本身非常简单,也难以包裹。那里有大量的错误信息和各种群体以正确的方式进行斗争。我认为使用WPF和Silverlight你应该使用MVVM,否则你将过度编码并尝试在新模型中解决问题,“旧”胜利形成的方法只会让你陷入困境。在Silverlight中更是如此,因为一切都需要是异步的(围绕这个是可能的,但你应该选择另一个平台)。
我建议您阅读这篇文章Simplifying the WPF TreeView by Using the ViewModel Pattern 仔细了解MVVM如何很好地实现,并允许您将获胜形式的心态转变为MVVM中的新思维方式。简而言之,当您想要完成某些事情时,首先将逻辑应用于ViewModel而不是View。你想选择一个项目?换一个图标?不要迭代UI元素,只需更新模型属性,让数据绑定完成细节。
答案 7 :(得分:-1)
在(模态)对话框中,我已经看到了很多MVVM实现的相同问题。当我查看MVVM模式的参与者时,我感觉缺少一些东西来构建一个连贯的应用程序。
但遗漏的是:
我的方法是引入一个(用例)控制器,它负责缺失点。如何在 WPF Application Framework (WAF) 示例应用程序中看到它的工作原理。