WPF MVVM与Razor Page MVVM的区别

5
WPF中的MVVM模式非常强调将ViewModel与UI完全分离,并且理想情况下在代码后台文件中没有或几乎没有任何内容。这使得可以将ViewModel用于不同类型的界面。
Razor Pages中的MVVM模式将代码后台作为ViewModel,与Web逻辑紧密耦合,在OnGet和OnPost方法中实现。
因此,精心设计的解耦WPF ViewModel无法作为Web ViewModel(或者可能可以从网页模型中使用?)
我是否遗漏了什么,为什么WPF中的MVVM(解耦)和Razor Pages中的MVVM(耦合)之间存在如此巨大的差异?
如果我们将Razor Pages方法应用于WPF,则代码后台将成为ViewModel--我从未见过任何人建议这样做。

2
据我所知,MVVM 是关于将 模型(Models)视图(Views) 解耦,而不是将 视图模型(ViewModels)视图(Views) 解耦的。 - vasily.sib
2个回答

2
让我们澄清一下:WPF和Razor Pages都引入了视图和视图模型之间的耦合。视图模型是数据表示层,以打破视图和模型之间的依赖关系。因此,可以更改视图而不修改任何模型。视图模型本身与模型相耦合,因为它获取所需数据(例如来自服务或数据库)。
在Razor Pages中,通过使视图模型实现抽象的PageModel并提供适当的可选操作处理程序(例如OnGet())来实现这种行为。每当发出针对页面的HTTP请求时,框架都会调用这些处理程序。您可以根据请求方法(例如GET,DELETE,POST,PUT等)获取或操作模型数据,然后将其呈现给视图。约定描述了这些处理程序的命名模式,以便框架可以识别它们。
因此,在WPF MVVM和Razor Pages MVVM中,您将找到层之间相同程度的耦合。由于RazorPages中的视图模型封装了特定页面的上下文,因此源文件命名遵循命名约定(“页面名称.cshtml.cs”),以在文件系统中显示关系。它不像WPF中视图的partial类文件那样是一个代码后台文件。

视图模型是数据表示层,旨在打破视图和模型之间的依赖关系。这并不完全正确,您描述的是MVC。MVVM是将视图与呈现逻辑分离,并支持双向绑定,无需使用来自Windows Forms时代的意大利面条式代码(txtName.Text 读取或设置值)。它是由微软专门为WPF引入(并发明)的。在WinForms中,您需要在代码后台中编写大量与格式化值以及检索/更新UI元素相关的代码。MVVM的发明就是为了解决这个问题。在ASP.NET Core中,VM仅被简化为一个没有任何逻辑的DTO类。 - Tseng
WPF/MVVM中的演示逻辑通常涉及更新其他控件内容(通过数据绑定和“INotifyPropertyChanged”解决),更新文本字段的状态(活动/非活动,按钮,通过“ICommand”和“CanExecute”处理)或协调用户输入与后台服务(命令调用服务以获取或提交数据 - 在MVC中由控制器完成)。大多数这些东西不适用于服务器端Web应用程序(但可以应用于客户端Web应用程序)。MVVM的目标是在UI更改或重新设计时重复使用它们。 - Tseng
MVVM 是 MVP 的一种形式,而 MVP 则是 MVC 的一种形式。我提到“数据表示层”是为了强调它是模型数据本身的中间层。MVVM (与 MVP、MVC 相同)的主要目标是将视图与模型或业务逻辑解耦。数据绑定只是实现此目的的机制。它是一种使用绑定使 Presenter(或控制器)和 View 之间依赖关系单向的 MVP 变体。 - BionicCode
不,数据绑定是MVVM被引入的主要原因。在WPF出现之前,没有MVVM。它是专门为WPF的数据绑定功能设计的。后来,该模式被其他框架采用,但最初是为WPF及其数据绑定而设计的。它是由两位微软工程师Ken Cooper和Ted Peters发明/定义/描述的:https://en.wikipedia.org/wiki/Model–view–viewmodel#Rationale - Tseng
我总是将它作为一个部分类,我认为它必须是这样的。 - ed22
显示剩余2条评论

-1

我不确定为什么你坚持使用 Razor Pages,当有 MVC(Model-View-Controller)可用。

你应该使用 MVC 模式。你可以获得相同的 Razor 语法,但是解耦了。

Razor Pages 是作为 WebForms 的一种继任者引入的(WebForms 本身试图模仿 Windows Forms,这与解耦无关)。

如果我们回到几年前的历史,MVVM 是为了使用 WPF 的双向模型绑定的全部功能,它充当 UI 和应用程序层之间的单独层,在其中可以放置演示逻辑(紧密耦合于演示,这是 UI 关注而不是应用程序层,后者与 UI 解耦)。

出于这个原因,MVVM 的 ViewModels 还具有(除了用于模型绑定的属性之外),例如 Commands,并且可能是 Navigation aware(即通过 Prism 的 INavigationAware 接口)。

在这种情况下,在服务器端的 Web 应用程序中,ViewModels 并没有太多价值,因为 HTTP 本身是无状态的,而 ViewModel 维护状态。

在MVC中的ViewModels被简化为DTOs(数据传输对象),具有基本验证(通过验证属性)。MVC应用程序中的ViewModels没有任何演示逻辑,因为它们被呈现为HTML,并且大多数演示逻辑是通过JavaScript在外部完成的(当按钮被点击时会发生什么,如何为用户格式化日期或货币)。
也就是说,您在ASP.NET Core应用程序中实际上不需要完整的ViewModels,至少不需要用于服务端部分。但是,如果您使用客户端技术(Angular、Vue.js、React),则可以利用ViewModels来增强功能并将其与视图解耦。
事实上,Angular组件很像ViewModels,并且完成了MVVM模式中ViewModels的同样任务(可以将服务注入其中,具有1向或2向绑定,输入验证和将演示逻辑放入其中)。
简而言之:您实际上不需要像MVVM中定义的ViewModels那样的ViewModels,只需要类似DTO的类来使它们在(Razor)视图模板中的消耗更容易。不要使用Razor Pages进行解耦。

2
MVC/MVVM中的“Model”不仅仅是“DTO类”。M-V-VM/M-V-C是层,而不是具体的类。例如,NavigationService是View的一部分,即使它是用代码编写的。这不像“View = XAML nothing else”。在MVC中,“Model”指的是“除了View或Controller之外的所有内容”,包括您的所有服务。但这取决于您使用@model MyModel绑定了什么。绑定EF实体?那是错误的方法。绑定DTO / ViewModel?那就没问题了。 - Tseng
2
我一直在阅读关于MVC与Razor页面的文章,大多数人都推荐使用Razor页面,除非是Web API或单页应用程序。他们说MVC控制器类会像病毒一样不断增长,代码分散到各种地方--从这个意义上讲,Razor页面具有更清晰的关注点分离。甚至微软也建议基于页面导航的网站使用Razor页面。 - Etienne Charland
如果WPF MVVM类维护状态,而Razor DTO是无状态的,那么在它们之间尝试重用ViewModels就没有意义了。因此,在Razor代码后台中放置HTML格式化代码是否可以?在WPF中,人们会为事件参数创建新类,以完全将ViewModel与WPF解耦 - 这实际上只有在创建另一种类型的有状态UI(如Linux界面或可能不基于Web API的Android应用程序)时才有用。在大多数情况下,似乎为了严格解耦WPF与其ViewModel而走额外的路程几乎没有什么好处。 - Etienne Charland
1
@EtienneCharland MVVM、MVP 或 MVC 模式的目标不是重用控制器或视图模型,而是应用程序的业务逻辑。您不希望每次修改或替换视图时都修改模型。这也使自动化 UI 测试成为可能,这也是一个巨大的收益。当视图与模型耦合时,没有模型就无法测试视图。假设您的模型由服务和数据库组成,这可能会产生巨大影响。 - BionicCode
1
@EtienneCharland 如果您不需要可测试性,或者您的应用程序很小,或者UI永远不会更改(例如设计或新的导航路径或结构),则可以相当地开发而无需使用这些模式。这是您的评估和个人决定。视图模型只是使视图不必直接访问模型成为可能。它打破了两者之间的依赖关系。同时,模型不必关心数据的呈现方式。 - BionicCode
显示剩余13条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接