首页 文章

MVVM毫无意义吗? [关闭]

提问于
浏览
89

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

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

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

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

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

8 回答

  • -1

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

    In summary, MVVM is not pointless.

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

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

    以下是此特定示例的解决方案:
    UI如何处理某个输入不是ViewModel 's business. I would add code to the View' s .xaml.cs文件,它实例化对话框并将相同的ViewModel实例(或其他东西,如果需要)设置为其DataContext .

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

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

    • 将XAML添加到视图中,并且.xaml.cs中没有任何内容

    • 在ViewModel中编写每个应用程序逻辑(除了可以直接使用UI元素操作的内容)

    • 应该由UI完成但与业务逻辑无关的所有代码都会进入.xaml.cs文件

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

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

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

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

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

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

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

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

    EDIT:

    这是一个非常好的视频,其 Headers 是Build your own MVVM framework . 值得一看 .

  • 5

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

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

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

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

  • 1

    我通过作弊处理对话问题 . 我的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设计对于大型应用程序可能很重要,在这种应用程序中,您需要更清洁的绝缘和更复杂的组合,但对于中小型应用程序,我认为一种实用的方法,通过适当的服务来暴露所需的钩子,已经足够了 .

  • 59

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

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

  • 0

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

    我的个人结论:

    MVVM vs MVC / PopUps&co

    • MVVM实际上是一个很好的模式,在大多数情况下,由于WPF中强大的数据绑定,它完全取代了MVC

    • 在大多数情况下,直接从演示者调用服务层是合法的实现

    • 由于语法,即使是非常复杂的List / Detail场景也可以由纯MVVM实现

    • 但是,当需要实现多个视图之间的复杂协调时,必须使用控制器

    • 可以使用事件;暗示在控制器中存储IView(或AbstractObserver)实例的旧模式已过时

    • 可以通过IOC容器在每个Presenter中注入控制器

    • Prism的IEventAggregator服务是另一种可能的解决方案,如果控制器的唯一用途是事件调度(在这种情况下它可以完全取代控制器)

    • 如果要动态创建视图,这是一个非常适合控制器的工作(在棱镜中,控制器将被注入(IOC)一个IRegionManager)

    • 模式对话框在现代复合应用程序中大部分都是过时的,除了强制确认之类的真正阻塞操作;在这些情况下,模态激活可以被抽象为在控制器内部调用的服务,并由专门的类实现还允许进行高级演示级单元测试 . 例如,控制器将调用IConfirmationService.RequestConfirmation(“你确定”),它将在运行时触发模态对话框显示,并且可以在单元测试期间轻松模拟

  • 8

    由于模式本身MVVM很棒 . 但WPF 's control library shipped with NET 4.0 data binding support is very limited, it is a lot better than WinForm, but still it'对于可绑定的MVVM来说还不够,我想它的功率大约是可绑定MVVM所需内容的30% .
    可绑定的MVVM:它是ViewModel仅使用数据绑定与View连接的UI .
    MVVM模式是关于ViewState的对象表示,它不是数据绑定,但它可以是任何东西 . 实际上,您可以在任何支持's events\callbacks, you can use it in pure WinAPI in WinForms (I did, and it'的UI工具包中使用MVVM模式,而不是使用event \ callbacks,甚至可以在文本控制台中使用它,就像使用MVVM模式重写DoS的Norton Commander一样 .

    简而言之:MVVM并非毫无意义,它很棒 . NET 4.0 WPF的控件库是垃圾 .

    Here is the simple proof of concept ViewModel which you can't data bind in pure MVVM manner using WPF.

    public class PersonsViewModel
    {
        public IList<Person> PersonList;
        public IList<ColumnDescription> TableColumns;
        public IList<Person> SelectedPersons;
        public Person ActivePerson;
        public ColumnDescription SortedColumn;
    }
    

    你可以't data bind WPF'的DataGrid列 Headers ,你不能数据绑定选定的行等等,你要么以代码简单的方式做,要么为这5行最简单的ViewModel写一个200行的XAML hack代码 . 你只能想象复杂的ViewModel会让事情变得更糟 .
    所以答案是简单的,除非您正在编写Hello World应用程序,在WPF中使用可绑定MVVM是没有意义的 . 您将花费大部分时间考虑hack绑定ViewModel . 数据绑定很不错,但准备好回退到事件的70%的时间 .

  • 4

    不,这并非毫无意义,但即使模式本身非常简单,也难以包裹 . 那里有大量的错误信息和各种群体以正确的方式进行斗争 . 我认为使用WPF和Silverlight你应该使用MVVM,否则你将过度编码并尝试在新模型中解决问题,“旧”胜利形成的方法只会让你陷入困境 . 在Silverlight中更是如此,因为所有东西都需要是异步的(可以解决这个问题,但你应该选择另一个平台) .

    我建议仔细阅读这篇文章Simplifying the WPF TreeView by Using the ViewModel Pattern,看看如何很好地实现MVVM,并允许你将你的胜利形式心态转变为MVVM中的新思维方式 . 简而言之,当您想要完成某些事情时,首先将逻辑应用于ViewModel而不是View . 你想选择一个项目?换一个图标?不要迭代UI元素,只需更新模型属性,让数据绑定完成细节 .

  • 5

    在(模态)对话框中,我已经看到了很多MVVM实现的相同问题 . 当我查看MVVM模式的参与者时,我感觉缺少构建连贯应用程序的东西 .

    • View 包含特定的GUI控件并定义用户界面的外观 .

    • ViewModel 表示演示文稿的状态和行为 .

    • Model 可以是来自域层的业务对象,也可以是提供必要数据的服务 .

    但遗漏的是:

    • 谁创建了ViewModels?

    • 谁负责应用程序工作流程?

    • 谁在需要相互通信时调解ViewModels?

    我的方法是引入一个负责缺失点的(用例) Controller . 如何在 WPF Application Framework (WAF) 示例应用程序中看到它的工作原理 .

相关问题