0


第六章:自建MVVM模式的简易项目框架

总目录


文章目录


前言

前面的几章为我们筑好了MVVM的基础,在这一章中我们将自己搭建一个MVVM模式下的简易项目框架。


一、MVVM是什么?

1.介绍

MVVM是一种模式,主要目的是降低界面和业务逻辑的耦合。
MVVM是Model-View-ViewModel(模型-视图-视图模型)的简写。是WPF开发过程中必不可少的一种开发模式,MVVM基本结构如下图所示:
在这里插入图片描述

  • View(视图) 就是交互界面,接受用户的输入和展示数据;
  • Model(模型) 是数据模型,项目中的对象,包含属性和行为,项目中的任何事物都可抽象为Model,例如项目中一个用户,我们可以抽象为一个用户的类,可以包含该用户的姓名,出生日期,电话等等信息
  • ViewModel(视图模型)是负责处理业务逻辑的核心。
  • 三者关系:在View和ViewModel中通过数据绑定将界面上元素的依赖属性与实现了INotifyPropertyChanged的ViewModel中的属性进行绑定,实现数据的实时更新机制。在View和ViewModel中通过命令绑定将界面上的操作用Command属性与ViewModel中实现了ICommand的命令进行绑定,实现了用户操作指令的下发。而Model 则是负责给ViewModel提供View所需的对象的数据模型。
  • 通过MVVM这种模式可以最大限度的降低UI界面,数据模型,逻辑业务之间的耦合。让View 将关注点优化呈现效果上,至于数据和操作只需绑定即可;让Model将关注点放在数据模型上,ViewModel将关注点放在处理核心业务逻辑上。

2.优势

  • 低耦合,View可以独立于Model变化和修改,一个ViewModel可以绑定到不同的”View”上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
  • 提高代码重用,可以把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑;
  • 独立开发,业务开发人员可以专注于业务逻辑和数据的开发,界面开发人员可以专注于页面的开发。

二、搭建MVVM项目框架

现在我们开始着手搭建MVVM项目框架,步骤如下:
(1)首先需要新建一个项目,创建Views,ViewModels,Models 三个文件夹,这样基本结构就搭建好了。

(2)将我们写的xaml页面放在Views目录下,一般就是命名为:xxxView,然后与之对应的视图模型命令为xxxViewModel放在ViewModels目录下,另外将需要的数据模型放置在Models目录下。

(3)再者需要创建一些辅助类的文件目录,一般会创建Resources用于存放一些资源如样式,字体,图片等等,创建一个Helper或者Common的目录,用于存放一些公用的方法类或者帮助类。

具体目录如下图所示:
在这里插入图片描述
这样一个简易的MVVM项目框架就搭建好了,当然在后面我们会接触到按照MVVM模式已搭建好的比较完善的框架供我们使用。

三、WPF中实现MVVM的重点内容

1.实现INotifyPropertyChanged接口

publicclassViewModelBase:INotifyPropertyChanged{publiceventPropertyChangedEventHandler? PropertyChanged;publicvoidOnPropertyChanged([CallerMemberName]string name=null){
            PropertyChanged?.Invoke(this,newPropertyChangedEventArgs(name));}publicvoidSet<T>(refT field,objectvalue,[CallerMemberName]string name=""){
            field=(T?)value!;
            PropertyChanged?.Invoke(this,newPropertyChangedEventArgs(name));}}

2.实现ICommand接口以及事件转命令

  • 实现实现ICommand接口
publicclassDelegateCommand:ICommand{publiceventEventHandler? CanExecuteChanged;publicDelegateCommand(Action executeActionNoPara,Func<bool> canExcuteFuncNoPara =null!){this.ExecuteActionNoPara = executeActionNoPara;this.CanExcuteFuncNoPara = canExcuteFuncNoPara;}publicDelegateCommand(Action<object?> executeAction,Func<object?,bool> canExcuteFunc =null!){this.ExecuteAction= executeAction;this.CanExcuteFunc = canExcuteFunc;}publicboolCanExecute(object? parameter=null){if(parameter==null)returnthis.CanExcuteFuncNoPara ==null?true:this.CanExcuteFuncNoPara.Invoke();returnthis.CanExcuteFunc ==null?true:this.CanExcuteFunc.Invoke(parameter);}publicvoidExecute(object? parameter =null){if(parameter ==null)this.ExecuteActionNoPara?.Invoke();elsethis.ExecuteAction?.Invoke(parameter);}publicAction ExecuteActionNoPara {get;set;}publicFunc<bool> CanExcuteFuncNoPara {get;set;}publicAction<object?> ExecuteAction {get;set;}publicFunc<object?,bool> CanExcuteFunc {get;set;}}
<StackPanelVerticalAlignment="Center"HorizontalAlignment="Center"Background="Red"><i:Interaction.Triggers><i:EventTriggerEventName="MouseDown"><i:InvokeCommandActionCommand="{Binding MouseDownCommand}"></i:InvokeCommandAction></i:EventTrigger></i:Interaction.Triggers></StackPanel>

3.实现窗体间的交互与数据传递

这一块儿的内容,当前系列之前并没有介绍,在这里介绍一下。
假如现在有这样一个需求,点击用户列表中的某一项,我需要打开一个窗口查看该项的详情页,那么必定就会涉及,新开一个窗口,并且窗体将需要传递数据。
如果我们在ViewModel 中按照下面代码实现:

privatevoidShowDetail(){UserDetailView view =newUserDetailView();//.....
            UserDetailView.Show();}

功能是可以实现,但是显然,不符合解耦的目的。MVVM的目的就是解耦,如果在ViewModel中操作View的内容,无疑又干回去!那我们应该去如何操作呢?定义一个专用于窗体间交互与数据传递的类,
窗体间需要做任何事情,都找"它"。

形如:

publicclassWindowManager{privatestaticDictionary<string, Action<object>> _dir =newDictionary<string, Action<object>>();publicstaticvoidRegister(string key,Action<object> action){if(!string.IsNullOrEmpty(key)&&!_dir.ContainsKey(key)){
                _dir.Add(key,action);}}publicstaticvoidDoAction(string key,object obj){if(!string.IsNullOrEmpty(key)&& _dir.ContainsKey(key)){
                _dir[key]?.Invoke(obj);}}}

当然,我们还可以根据项目对该类做完善和扩展。

4.页面切换时数据的处理

未完待续

5.特别说明

  • View中依赖属性需要绑定ViewModel中的属性
  • 注意绑定的是ViewModel中的属性,不是字段。
  • 注意为了实现View和Model的隔离,View是绑定ViewModel中属性,而不可以直接绑定Model层,Model可以为ViewModel提供数据模型,如我们常见场景Model中有个UserInfo类,然后再在ViewModel将UserInfo 申明为一个属性User,View会绑定ViewModel中User属性
  • 那么何时将属性设置在ViewModel中,何时将属性放在Model中供ViewModel使用呢? ①一般页面上展示集合的情况,都是需要将数据模型放在Model层,然后通过ViewModel申明为一个泛型集合来使用; ②在界面上有一些不同区域需要展示不同数据的情况,如,左边需要放用户数据,右边需要放订单数据或其他什么数据,就需要在Model中分别定义数据模型,然后ViewModel中使用; ③在少数情况下可以直接在属性申明在ViewModel中,而省去在Model中定义数据模型,这类情况一般就是该属性复用的地方极少,或者只有一两个零散的属性会在View中需要使用。
  • 在绑定集合的时候,若要设置动态绑定,以便集合中的插入或删除操作可以自动更新 UI,则集合必须实现 INotifyCollectionChanged 接口,WPF 提供 ObservableCollection 类,该类是公开 INotifyCollectionChanged 接口的数据集合的内置实现。如果还要实现集合每项对象属性值的变化通知到UI则还需要集合的数据对象实现INotifyCollectionChanged。
  • 解耦的根本在个人理解来看,就是加个"第三方代理商",有什么事情都找代理商,比如要将View和Model 解耦,就加了一个ViewModel用于两者的解耦。

结语

以上就是本文要介绍的内容,希望以上内容可以帮助到你,如文中有不对之处,还请批评指正。


标签: wpf ui

本文转载自: https://blog.csdn.net/qq_39847278/article/details/127914813
版权归原作者 鲤籽鲲 所有, 如有侵权,请联系我们删除。

“第六章:自建MVVM模式的简易项目框架”的评论:

还没有评论