一、为什么称MVVM被滥用
1、什么是MVVM?
MVVM是Model-View-ViewModel的简写。它本质上就是 MVC的改进版。MVVM模式有助于将应用程序的业务和表示逻辑与 用户界面 (UI) 清晰分离。 保持应用程序逻辑和UI之间的清晰分离有助于解决许多开发问题,并使应用程序更易于测试、维护和演变。 它还可以显著提高代码重用机会,并允许开发人员和 UI设计人员在开发应用各自的部分时更轻松地进行协作。
MVVM可用于跨平台软件的代码架构设计。
2、如何被滥用的
现在一说WPF就需要会MVVM,这股风起源于微软对WPF的宣传。MVVM固然有优势,但是微软描述了MVVM的使用场景。而大多数作者在描述MVVM时,不会去强调MVVM的使用场景。时间一长‘不会MVVM就不算会WPF’就真的变成了写WPF就得用MVVM,而不是MVVM很重要了。对此我希望大家可以正确理解MVVM不要滥用。
应用程序更易于测试、维护和演变。但是有以下缺点:
MVVM本身会增加代码量,业务代码不复杂的小界面不适合使用,会增加编码时间和阅读代码的困难度。
ViewModel分割了model与View间的直接关系,让操作View使用的代码变多;降低编程的快感;
对于只有一两位开发人员的小型应用程序来说,这种严格分离带来的好处可能无法抵消编码所浪费的时间。原有的事件机制更适合这种程序;
对于复杂的View,我们在不使用MVVM时,建立一个有嵌套结构的Model就已经感觉到困难,再加一个MVVM的ViewModel要考虑时事情就变多了。可能需要重构ViewModel才能解决。
3、什么时候该用?什么时候不该用?
(1)该用:
① 对View修改频繁,则用MVVM(无需触及代码即可重新设计应用 UI,前提是视图完全在 XAML 中实现);
应用程序的业务开发人员独立时,可以用MVVM模式分离View与Model;但是要消耗一些时间做好沟通,不要影响上线周期;
③ View 与 ViewModel 的分离还使得 ViewModel 更有利于单元测试和重用;需要对View进行独立测试或者排除View进行单元测试时,则选择MVVM;
④ 大型项目;
(2)不该用:
① 对View后续控件改动不大;
应用程序业务不复杂的小项目;
(3)都可,根据软件实际情况和代码开发者习惯进行考虑:
① 中等项目,后续会改动,界面改动不频繁。
4、使用MVVM后,代码如何写
记住下面的原则即可:
1、Model对业务负责,ViewModel对View负责;ViewModel中使用Model中的数据写View相关的逻辑,业务代码写在其他类(如BLL、Service)中,也可直接写在Model中;
2、Model不了解平台或 ViewModel,Viewmodel可以直接访问Model上的属性和方法,
3、WPF中的窗体展示可使用如下代码(传参示例)
二、原生MVVM案例
项目地址: https://gitee.com/qq28069933146_admin/wpf_mvvm_simple
1、MVVM知识点
想要创建一个完整的MVVM,需要用到以下类型或修饰词:
- Window.DataContext:View Window强绑定ViewModel;
- Binding:View绑定ViewModel中的变量、事件;
- INotifyPropertyChanged:用于ViewModel通知View刷新;ViewModel继承该类,并实现PropertyChanged、OnPropertyChanged;
- ICommand:用于VIew通知ViewModel响应控件事件;创建ICommand的实现类RelayCommand,并实现CanExecuteChanged,CanExecute,Execute;
2、创建Model
3、创建View
注意已下代码:
- Window.DataContext:View Window强绑定ViewModel;
- Binding:View绑定ViewModel中的变量、事件;
4、创建ViewModel
- ViewModelBase为INotifyPropertyChanged的实现类;
- RelayCommand为ICommand的实现类;
5、实现INotifyPropertyChanged
INotifyPropertyChanged:用于ViewModel通知View刷新;ViewModel继承该类,并实现PropertyChanged、OnPropertyChanged;
6、实现ICommand
ICommand:用于VIew通知ViewModel响应控件事件;创建ICommand的实现类RelayCommand,并实现CanExecuteChanged,CanExecute,Execute;
7、效果
8、补充:
(1)若ViewModel中有List<>或Array[]类型的变量,请使用ObservableCollection<>代替;ObservableCollection知识见:WPF-双向绑定通知机制之ObservableCollection;
三、简化MVVM代码量(CommunityToolkit.MVVM)
项目地址: https://gitee.com/qq28069933146_admin/wpf_mvvm_simple
在一、中我们完成了原生MVVM的开发,能够发现一个问题,ViewModel中我们添加一个成员对象就需要添加下面一段代码
那我们能不能像平时写model一样,只添加public string Name{get;set;} = string.Empty;
呢,大概是肯定的。我们只需要引入CommunityToolkit.MVVM
包即可;当然代码也不可能是public string Name{get;set;} = string.Empty;
,而是[ObservableProperty]private string _name = string.Empty;
,类名也需要继承ObservableObject
并添加partial
修饰词,完整代码如下:
1、CommunityToolkit.MVVM可简化哪些代码
- 可简化上面代码块中的代码;即
ViewModel继承ObservableObject并添加partial修饰词
,即可省略OnPropertyChanged
; - 省略
OnPropertyChanged
就意味着可删除ViewModelBase
类; ObservableObject
自带RelayCommand
的实现,可删除我们项目里的RelayCommand
类(使用案例如上代码);- 可省略ButtonCommand变量直接写ButtonFunCommand;但为了好找到ButtonCommand,本文章不推荐省略;
2、解析RelayCommand类
(1)RelayCommand无参与有参
无参
有参
(2)AsyncRelayCommand异步无参与有参
无参
有参
3、IOCDI(CommunityToolkit.MVVM)
Light用于实现MVVM;CommunityToolkit.MVVM的IOCDI功能继承于MVVMLight。
所以 CommunityToolkit.MVVM的IOCDI可学可不学,微软推荐过的WPF IOCDI库有Microsoft.Extensions.DependencyInjection、Unity;
作者:꧁执笔小白꧂