导图社区 WPF-MVVM
WPF框架的MVVM导图,MVVM是Model-View-ViewModel(模型-视图-视图模型)的缩写形式,它通常被用于WPF或Silverlight开发。
编辑于2022-01-20 16:00:16MVVM
MVVM设计模式
是一种设计思想,强调分层架构
Model
数据模型
一般与View中需要进行显示或操作的内容相关
View中需要的数据显示与操作,由Model接收处理
View
交互操作界面
界面布局
界面逻辑
没有任何业务逻辑参与的界面操作逻辑
动画
ViewModel
WPF的底层支持
数据显示与通知
Model与ViewModel中均可处理
Model与ViewModel的区别
ViewModel是Model的合集
ViewModel中可以包含0个或多个Model
Model通过ViewModel将数据反馈在View中
当遇到集合列表显示时,需要使用对应的Model做为集合子项
默认情况
只可将数值从View向Model或ViewModel更新
假定双向绑定
不支持双向更新
INotifyPropertyChanged
关键成员
PropertyChanged事件
如果需要将属性值变化通知到页面,需要在属性Set访问器中执行PropertyChanged事件
接收一个PropertyChangedEventArgs参数,传入属性名称
不传入属性名称,写“”时,通知所有属性
注意性能
列表集合变化通过
ObservableCollection
数据验证
页面进行校验错误信息捕获与显示
参照【07依赖属性与绑定课程】
Exception
在属性Set访问器中抛出一个ApplicationException异常
ValidationRule
对很个需要校验的属性创建一个对应的类,并继承自ValidationRule类
IDataErrorInfo
通过特性添加条件进行检查
常用特性
Required
StringLength
Range
RegularExpression
CustormValidation
自定义Attribute
创建类
继承自ValidationAttribute类
重写IsValid方法
返回True:校验通过
返回False:校验失败
在类名上添加特性[AttriguteUsage(AttributeTargets.Property)]
常用插件
PropertyChanged.Fody
通过NuGet获取
通过编译时给指定对象添加通知代码
使用
给指定类添加特性
ImplementPropertyChanged
废弃
AddINotifyPropertyChangedInterface
只要继承自INotifyPropertyChanged的类
常用特性
AlsoNotifyForAttribute
DoNotNotifyAttribute
DependsOnAttribute
DoNotSetChangedAttribute
DoNotCheckEqualityAttribute
BeforeAfter
添加OnPropertyChanged(string propertyName, object before, object after)方法
自动添加属性变化前后的值
EqualityChecking
是否添加值修改判断
判断新旧值是否一致
IsChanged
如果类中添加此属性,其他属性值变化时,自动将此属性设置为True
可配合DoNotSetChanged特性使用
行为命令的分离
预定义命令
MediaCommands
24个
ApplicationCommands
23个
NavigationCommands
16个
ComponentCommands
27个
EditingCommands
54个
基本上都需要自己实现逻辑
不需要自己实现逻辑的内置命令
Cut
Copy
Paste
Undo
Redo
自定义命令
继承自RoutedCommand
可指定快捷键
统一状态管控
业务逻辑统一
实现ICommand接口
CanexecuteChanged事件
CanExecute方法
判断绑定此命令的对象是否被激活
返回True:绑定此命令的对象可用
返回False:绑定此命令的对象不可用
不主动判断
通过触发CanExecuteChanged事件调用此判断
Execute方法
命令被执行时的调用方法
方法参数对应页面绑定中的CommandParameter内容
其他事件绑定命令
并不是所有控件都有Command属性
鼠标输入绑定
对象的InputBindings属性
指定鼠标动作
LeftClick
LeftDoubleClick
MiddleClick
MiddleDoubleClick
RightClick
RightDoubleClick
WheelClick
None
非Command属性、常规事件绑定命令
程序集:System.Windows.Interactivity.dll
添加程序集引用
在对象中使用
无法做鼠标事件参数传递
借助第三方库,比如MvvmLight
常用框架
MvvmLight
了解
第三方框架
轻量
已停止维护
2年前
代码量少,利于学习编程框架
每个组件均可单独使用,互不干涉
MVVM工具包
引入框架
Nuget包安装(任选一)
MvvmLight
MvvmLightLibs
区别在于在Framework框架下,Libs不会自动创建一些文件
主要程序集
GalaSoft.MvvmLight.dll
MvvmLight的核心功能
数据绑定
ObservableObject
ViewModelBase
提供设计模式与运行模式分离思想
命令绑定
RelayCommand
消息对象
Messenger
GalaSoft.MvvmLight.Extras.dll
Ioc容器
GalaSoft.MvvmLight.Platform.dll
事件绑定
EventToCommand
DispatcherHelper
对MVVM的支持
ObservableObject
实现INotifyPropertyChanged接口
完成基本功能封装
RaisePropertyChanged
Set
ViewModelBase
继承自ObservableObject
提供设计模式与运行模式分离思想
IsInDesignMode
IsInDesignModeStatic
RelayCommand
常规命令
泛型命令
RaiseCanExecuteChanged
ViewModelLocator
在程序入口处实例化,全局可用
提供全局对象注册与实现
提供统一的IOC容器
SimpleIoc
ViewModel注册
SimpleIoc.Default.Register<MainViewModel>();
一般接口对象注册
SimpleIoc.Default.Register<IDataService, MyDataService>();
以属性方式提供ViewModel的访问
View中绑定ViewModelLocator的对应属性
Messenger
原理
不关心接收者,不关心发送者,不关心发送内容
全局注册委托
注册
常规消息
NotificationMessage
NotificationMessageAction<T>
监控属性变化
PropertyChangedMessage
通过参数的PropertyName获取属性名称
发送
全局广播
指定Token发送
指定接收者
DispatcherHelper
接管WPF默认的Dispatcher对象
程序入口初始化
DispatcherHelper.Initialize()
程序任意地方使用
DispatcherHelper.CheckBeginInvokeOnUI(() => { list.Add("789"); });
Prism
了解
微软官方框架
目前版本8.0
一组设计模式的的实现
MVVM
IoC
为了支持开发结构良好、易维护、扩展应用
支持Xaml类应用开发
WPF
Xarmarin
Uno
引入框架
安装扩展
Prism Template Pack
代码片段
项目模板
对象模板
自行了解
Nuget包安装
Prism.Core
与平台无关,与其他平台框架通用
Prism.Wpf
针对WPF开发的功能封装
Prism.Unity
安装此包会自动包含Core与Wpf包
使用微软自家的Ioc容器框架-Unity
应用中相关对象由Ioc管控
使用时自动注入
初始化Prism项目
PrismBootstrapper
新版本不建议使用
新建类继承PrismBootstrapper类,并重写方法
CreateShell
创建应用程序主Shell(窗口)
RegisterTypes
注册应用程序中可能会用到的自定义对象
接口
实现
移除App.xaml中的StartupUri属性
重写App.xaml.cs中的OnStartup方法
创建类实例
执行Run方法
PrismApplication
Application与PrismBootstrapper类的合集
修改应用入口App对象继承自PrismApplication
重写方法CreateShell
重写方法RegisterTypes
默认情况下必须重写此两个方法,否则报错
对MVVM的支持
BindableBase
RaisePropertyChanged
SetProperty
OnChanged
数据校验
ErrorsContainer
集合变化时,触发ErrorsChanged事件
INotifydataErrorInfo
DelegateCommand
必传参数
ExecuteMethod
可选参数
CanExecuteMethod
必须执行命令的RaiseExecuteChanged事件
ObservasProperty
指定观察的属性
不需明确的执行RaiseExecuteChanged事件
ObservesCanExecute
指定监控一个布尔型属性
InvokeCommandAction
任意事件绑定
TriggerParameterPath
不指定时传递事件对象本身
复合命令
应用场景
全局工具栏操作(比如保存)
定义
接口
实现
注册
由RegisterTypes方法中注册
使用
需要统一调用的ViewModel中(一般由命令执行)添加相关对象与属性
添加ICompositeCommands类型的属性
注入ICompositeCommans
将实例赋值给属性
每个单独的ViewModel中,注入ICompositeCommands实例
为实例对象的DoCommand属性注册一个常规命令
_applicationCommands.DoCommand.RegisterCommand(UpdateCommand);
事件聚合器
继承自PubSubEvent<T>
在所需要对象构造函数中注入IEventAggregator
订阅
通过委托接收消息
消息过滤
消息执行线程指定
发布
取消订阅
ViewModelLocator
自动注入
Prism命名空间
xmlns:prism="http://prismlibrary.cpm/"
prism:ViewModelLocator.AutoWireViewModel="True"
命名规律
文件夹
Views
VIewModels
对象
View名称不做要求,或以View结尾
ViewModel必须与View名称+ViewModel命名
如果View以“View”结尾,则“View”忽略
修改命名规则
重写App.xaml.cs中的ConfigureViewModelLocator方法
调用方法参数的SetDefualtViewTypeToViewModelTypeResolver方法
根据自定义规则匹配View与ViewModel
命名不规律
重写App.xaml.cs中的ConfigureViewModelLocator方法
通过参数的Register方法执行匹配注册
类型方式
typeof(MainView)
typeof(MainViewModel)
泛型方式
Register<MainView,MainViewModel>()
手动设置DataContext
模块化
Shell
App对象中CreateShell所返回的窗体对象
Region
区域,相当于窗口布局
最终在对应Region呈现指定View
区域的定义与注册
区域适配器
ContentControlRegionAdapter
与ContentControl绑定
可执行Activate与Deactivate
ItemsControlRegionAdapter
与ItemsControl绑定
SelectorRegionAdapter
与Selector绑定
TabControlRegionAdapter
与TabControl绑定
自定义适配器
继承RegionAdapterBase<容器类型>类
重写Adapt方法,告诉适配器以什么方式添加视图
生写PrismApplication的ConfigureGegionAdapterMappings方法
执行注册
区域定义
XAML
prism:RegionManager.RegionName
指定Region名称表示注册完成
prism:RegionManager.RegionContext
可以给当前区域指定数据上下文,用于数据绑定
代码方式
RegionManager.SetRegionName(页面对象, "指定名称");
加载视图
利用RegionManager对象的RegisterViewWithRegion方法
利用Region对象的Add方法
生存期管理
ViewModel实现IRegionMemberLifetime接口
设置属性KeepAlive
True:View离开时不销毁
False:View离开后销毁
Activate&Deactivate
需要获取View实例对象
不适合在ViewModel中执行
通过Region执行而非RegionManager
被执行对象必须与Region中的对象为同一个实例
只能与ContentControl类的Region配合使用
状态监控
ViewModel实现IActiveAware接口
通过属性IsActive判断激活状态
区域导航
在PrismApplication或Module对象的RegisterTypes方法中以RegisterForNavigation方法对View进行注册
【发】在需要执行导航的地方(比如命令)执行RequestNavigate方法
需要注入RegionManager对象
基本参数
Region名称
View名称
导航完成回调参数
导航参数传递
传递NavigationParameters集合对象
以键值对形式
【收】导航信息接收
ViewModel实现INavigationAware接口
通过OnNavigatedTo方法接收传递参数与导航日志
通过IsNavigationTarget返回值判断是否显示已有视图
True:显示已有视图
False:新建视图
导航确认
是否从当前页面离开
实现IConfirmNavigationRequest接口
完成ConfirmNavigationRequest方法
通过回调参数ContinuationCallback返回状态
True:确认离开
False:不离开
Module
属于一类功能的集合
View
ViewModel
Model
定义
实现IModule接口
实现OnInitialized接口方法
实现RegisterTypes接口方法
属于PrismApplication的功能延伸,但只有此两个方法实现
注册与发现
配置文件方式
App.config
添加Modules父节点
添加Module子节点
assemblyFile
moduleType
moduleName
startupLoaded
重写PrismApplication类的CreateModuleCatalog方法
return new ConfigurationModuleCatalog();
XML文件
XML文件创建
重写PrismApplication类的CreateModuleCatalog方法
return new XamlModuleCatalog(new Uri("/Modules;component/ModuleCatalog.xaml", UriKind.Relative));
代码方式
通过IModuleCatalog
泛型方式
重写PrismApplication类的ConfigureModuleCatalog方法
执行参数的AddModule方法
传入一个Module类型
ModuleInfo对象
重写PrismApplication类的ConfigureModuleCatalog方法
执行参数的AddModule方法
接收一个ModuleInfo类型的参数
ModuleName
ModuleType
InitializationMode
初始化方式
启动时初始化
按需初始化
通过IModuleManager
随时动态加载Module
LoadModule
LoadModuleCompleted事件监控加载完成
目录扫描
生写PrismApplication的CreateModuleCatalog方法
创建DirectoryModuleCatalog对象并返回
设置ModulePath
弹出窗口处理
子窗口处理
ViewModel实现IDialogAware接口
OnDialogOpened
接收传入参数
父窗口处理
注入IDialogService对象
执行打开弹窗
IDialogService实例对象的ShowDialog方法
View的注册名称
传递参数
反馈回调
指定父窗体
窗口定义
样式处理
自定义弹窗对象
实现IDialogWindow接口
在App的RegisterTypes方法中注册
RegisterDialogWindow
指定名称
不指定名称
以View类名注册
接口汇总
自动注入接口
由引用类的构造函数添加对应接口参数
通过容器获取对象实例时,自动注入对应实例
常用接口
IUnityContainer
任何地方注册的对象都在这个容器中
根容器
IContainerExtension
扩展接口,两个接口的合集
IContainerProvider
IContainerRegister
IContainerProvider
提供对象解析功能
IContainerRegistry
提供对象注册功能
IModuleCatalog
提供Module注册功能
IDialogService
处理弹窗操作
ShowDialog
IModuleManager
管理Module集合
加载Module
IRegionManager
管理Region集合
注册Region
IEventAggregator
获取聚合事件
IRegionBehaviorFactory
管理Region的默认行为
对应PrismApplication的ConfigureDefaultRegionBehaviors方法
IRegionNavigationJournalEntry
得到一个导航日志条目
IRegionNavigationJournal
提供某区域的当前导航日志
返回导航
前进导航
自定义对象注入
自定义接口
实现自定义接口
Register<自定义接口,实现类>()
继承实现接口
IDialogWindow
自定义弹窗窗口时需要实现此接口
IDialogAware
弹窗内容对象对应的ViewModel实现此接口
接收参数
返回结果
IActiveAware
监控View激活与失效状态
INavigationAware
获取导航参数与导航日志信息
IConfirmNavigationRequest
Region导航操作时,确认是否离开当前View
IRegionMemberLifetime
管理VIew的生存期
IModule
创建Module对象