MVVM毫无意义吗?

Joe*_*ers 90 .net wpf mvvm

正统的MVVM实现是没有意义的吗?我正在创建一个新的应用程序,我考虑了Windows窗体和WPF.我之所以选择WPF,是因为它具有前瞻性,并提供了很大的灵活性.使用XAML的代码更少,更容易对UI进行重大更改.

由于WPF的选择是显而易见的,我认为我可以使用MVVM作为我的应用程序架构,因为它提供了可混合性,分离问题和单元可测试性.从理论上讲,它看起来很像UI编程的圣杯.这个简短的冒险; 然而,已经变成了一个真正的头痛.正如在实践中所预期的那样,我发现我已将一个问题换成了另一个问题.我倾向于成为一个强迫性的程序员,因为我想以正确的方式做事,这样我才能获得正确的结果,并可能成为更好的程序员.MVVM模式刚刚落后于我对生产力的考验,刚刚变成了一个令人讨厌的大黑客!

明显的例子是添加对模态对话框的支持.正确的方法是建立一个对话框并将其绑定到视图模型.让这个工作很难.为了从MVVM模式中受益,您必须在应用程序的各个层中的多个位置分发代码.您还必须使用深奥的编程结构,如模板和lamba表达式.让你盯着屏幕挠挠头的东西.正如我最近发现的那样,这使得维护和调试成为一场噩梦.我有一个关于盒子正常工作,直到我第二次调用它时出现异常,说它一旦关闭就无法再显示对话框.我必须为对话框窗口添加一个关闭功能的事件处理程序,在IDialogView实现中添加另一个,最后在IDialogViewModel中添加另一个.我以为MVVM会让我们免于这种奢侈的hackery!

有几个人为这个问题提供竞争解决方案,他们都是黑客,并没有提供一个干净,易于重复使用的优雅解决方案.大多数MVVM工具包都会掩盖对话框,当它们确实解决它们时,它们只是不需要自定义接口或视图模型的警报框.

我打算放弃MVVM视图模式,至少是它的正统实现.你怎么看?如果你有任何问题,是否值得为你带来麻烦?我只是一个不称职的程序员,还是MVVM不是它被炒作的东西?

Ven*_*emo 61

对不起,如果我的答案变得有点长,但不要怪我!你的问题也很冗长.

总之,MVVM并非毫无意义.

明显的例子是添加对模态对话框的支持.正确的方法是建立一个对话框并将其绑定到视图模型.让这个工作很难.

是的,确实如此.
但是,MVVM为您提供了一种将UI外观与逻辑分离的方法.没有人强迫你到处使用它,没有人拿着枪对着你的额头,让你为一切创建一个单独的ViewModel.

以下是我对此特定示例的解决方案:
UI如何处理某个输入,这不是ViewModel的业务.我将向View的.xaml.cs文件添加代码,该文件实例化对话框并将相同的ViewModel实例(或其他东西,如果需要)设置为其DataContext.

为了从MVVM模式中受益,您必须在应用程序的各个层中的多个位置分发代码.您还必须使用深奥的编程结构,如模板和lamba表达式.

好吧,你不必在几个地方使用它.这就是我解决它的方法:

  • 将XAML添加到View中,而.xaml.cs中没有任何内容
  • 在ViewModel中编写每个应用程序逻辑(除了可以直接使用UI元素操作的内容)
  • 所有应由UI完成但与业务逻辑无关的代码都会进入.xaml.cs文件

我认为MVVM的目的主要是分离应用程序的逻辑和具体的UI,因此可以轻松修改(或完全替换)UI.
我使用以下原则:View可以从ViewModel知道并假设它想要的任何东西,但ViewModel可以知道关于View的NOTHING.
WPF提供了一个很好的绑定模型,您可以使用它来实现这一目标.

(顺便说一下,如果使用正确,模板和lambda表达式并不深奥.但如果你不想,请不要使用它们.)

让你盯着屏幕挠挠头的东西.

是的,我知道这种感觉.正是我第一次看到MVVM时的感受.但是一旦掌握了它,就不会再感觉不好了.

我有一个关于盒子工作正常...

你为什么要把ViewModel放在一个关于盒子的后面?没有意义.

大多数MVVM工具包都会掩盖对话框,当它们确实解决它们时,它们只是不需要自定义接口或视图模型的警报框.

是的,因为UI元素在同一个窗口或另一个窗口中,或者目前正在围绕火星运行的事实不是ViewModels关注的问题.
关注点分离

编辑:

这是一个非常好的视频,标题是构建自己的MVVM框架.值得一看.

  • 关于使用代码隐藏的建议+1.一种常见的误解是在MVVM中使用代码隐藏是"坏"的......但对于纯粹与UI相关的东西,这就是要走的路. (12认同)
  • @Thomas:你是对的,关于MVVM最大的神话是MVVM的目的是摆脱代码隐藏.目的是从后面的代码中获取非UI ocde.将仅使用UI的代码放在ViewModel中就像将问题域代码放在代码隐藏中一样糟糕. (7认同)
  • @Venemo,我认为你可以使用自定义行为等技术封装你想要放在代码隐藏中的很多东西,如果你发现自己反复编写粘合代码,这很方便.但总的来说,我认为使用代码隐藏更好的方法比使用笨拙的XAML更好.在我看来,主要关注的是确保代码隐藏中没有任何内容足以保证单元测试.任何足够复杂的东西最好封装在ViewModel或扩展类中,比如Behavior或MarkupExtension. (3认同)
  • 最后三个单词+1.但其余的答案也很好.:) (2认同)

ima*_*ima 8

让这个工作很难.为了从MVVM模式中受益,您必须在应用程序的各个层中的多个位置分发代码.您还必须使用深奥的编程结构,如模板和lamba表达式.

对于普通的模态对话框?你肯定在那里做错了 - MVVM实现不一定非常复杂.

考虑到你是MVVM和WPF的新手,很可能你到处使用次优解决方案并且不必要地使事情复杂化 - 至少我第一次使用WPF时这样做了.在放弃之前确保问题确实是MVVM而不是你的实现.

MVVM,MVC,Document-View等是一个古老的模式家族.有一些缺点,但没有你所描述的致命缺陷.


Dan*_*ant 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();
}
Run Code Online (Sandbox Code Playgroud)

这将所有Dialog执行放在一个地方,并且可以很容易地将其删除以进行单元测试.我遵循对话框的客户端必须创建适当的ViewModel的模式,然后他们可以根据需要进行配置.执行调用块,然后客户端可以查看ViewModel的内容以查看Dialog结果.

更加"纯粹"的MVVM设计对于大型应用程序可能很重要,在这种应用程序中,您需要更清洁的绝缘和更复杂的组合,但对于中小型应用程序,我认为一种实用的方法,通过适当的服务来暴露所需的钩子,已经足够了.


小智 5

我正在使用PRISM进行相当复杂的MVVM开发,因此我已经不得不应对这种担忧.

我的个人结论:

MVVM vs MVC/PopUps&co

  • MVVM实际上是一个很棒的模式,在大多数情况下,由于WPF中强大的数据绑定,它完全取代了MVC
  • 在大多数情况下,直接从演示者调用服务层是合法的实现
  • 由于{Binding Path = /}语法,即使是非常复杂的List/Detail场景也可以由纯MVVM实现
  • 但是,当需要实现多个视图之间的复杂协调时,必须使用控制器
  • 可以使用事件; 暗示在控制器中存储IView(或AbstractObserver)实例的旧模式已过时
  • 可以通过IOC容器在每个Presenter中注入控制器
  • 如果控制器的唯一用途是事件调度(在这种情况下它可以完全取代控制器),Prism的IEventAggregator服务是另一种可能的解决方案
  • 如果要动态创建视图,这是一个非常适合控制器的工作(在棱镜中,控制器将被注入(IOC)一个IRegionManager)
  • 在现代复合应用程序中,模态对话框大多已经过时,除了强制确认等真正的阻塞操作; 在这些情况下,模态激活可以被抽象为在控制器内部调用的服务,并由专门的类实现,这也允许高级表示级单元测试.例如,控制器将调用IConfirmationService.RequestConfirmation("你确定"),它将在运行时触发模态对话框显示,并且可以在单元测试期间轻松模拟


RMa*_*art 5

设计模式可以帮助您,而不是阻碍.成为优秀开发人员的一小部分是知道何时"违反规则".如果MVVM对于任务来说很麻烦,并且您已确定未来的值不值得付出努力,那么请不要使用该模式.例如,正如其他海报所评论的那样,为什么要通过所有开销来实现一个简单的框?

设计模式从未打算过教条.

  • 正确.一个简单的框应该很简单,但是如果你必须显示诸如版本,许可,运行过程,公司名称等信息,那么这就是生活在某个地方的所有信息.在标准表单中,您可以绑定所有信息并使用它完成.MVVM说你应该为它创建一个视图模型,这是多余的. (2认同)