1.什么是MVVM
MVVM,是Model-View-ViewModel的简写,是M-V-VM三部分组成。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,其中ViewModel将视图 UI 和业务逻辑分开,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。
MVVM采用双向数据绑定,view中数据变化将自动反映到viewmodel上,反之,model中数据变化也将会自动展示在页面上。把Model和View关联起来的就是ViewModel。ViewModel负责把Model的数据同步到View显示出来,还负责把View的修改同步回Model。
MVVM核心思想,是关注model的变化,让MVVM框架利用自己的机制自动更新DOM,也就是所谓的数据-视图分离,数据不会影响视图。
2.MVVM分层结构
Views
ViewModels
Models
3.PropertyChanged.Fody插件
作用:简化代码
实现原理:在编译时候,在属性中实现INotifyPropertyChanged
期间遇到搜不到该插件的,问题解决
4.MVVM命令对象
5.MVVM模式下的行为处理
什么是命令:特定的指令、有明确的执行内容,带有一定的强制性,参照事件,但与事件不同。
命令的用途:
1)第一个目的是将语义和调用命令的对象与执行命令的逻辑分开
2)统一的指示操作是否可用
自定义命令ICommand接口
- 是否可执行方法CanExecute
- 主要执行逻辑:Execute
- 触发检查是否可执行:CanExecuteChanged
using PropertyChanged;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using WPFMVVM模式.Base;
namespace WPFMVVM模式.Models
{
//模型
[AddINotifyPropertyChangedInterface]
internal class MainModel
{
[DoNotCheckEquality]//强制不做旧值比对(默认情况下会自动添加比对代码)
[DoNotNotify]//不需要通知
public double _value1 { get; set; } = 123;
public double Value1
{
get { return _value1; }
set
{
_value1 = value;
BtnCommand1.DoCanExecuteChanged();
}
}
[DependsOn("Value1")]//Value1变化的时候通知一下Value2
public double Value2 { get; set; } = 23;
[AlsoNotifyFor("Value1")]//通知Value3时候,同时通知Value1
public double Value3 { get; set; }
public MainModel()
{
BtnCommand1 = new CommandBase()
{
DoExecute = new Action<object>(Hello),
DoCanExecute = new Func<object, bool>(CanHell)
};
BtnCommand2 = new CommandBase()
{
DoExecute = new Action<object>(World),
DoCanExecute = new Func<object, bool>(CanWorld)
};
}
public CommandBase BtnCommand1 { get; set; }
public CommandBase BtnCommand2 { get; set; }
private void Hello(object obj)
{
this.Value3 = this.Value1 + this.Value2;
BtnCommand2.DoCanExecuteChanged();
}
private void World(object obj)
{
}
// Hello命令的的可用判断逻辑
public bool CanHell(object obj)
{
// 命令可用条件
// 当调用 CanExecuteChanged 事件后,重新进行条件检查
return this.Value1 != 0;
}
// World命令的可用判断逻辑
public bool CanWorld(object obj)
{
return this.Value3 != 0;
}
}
}
通过CommandManger全局变量检查按钮是否可用
6.预定义与内置命令
预定义命令
内置命令
自定义UICommand
任意事件的绑定处理
7.MVVM模式中的跨模块交互
internal class WindowManager
{
static Dictionary<string, WinEntity> _windows = new Dictionary<string, WinEntity>();
/// <summary>
/// 注册
/// </summary>
/// <param name="type"></param>
public static void Register(Type type, Window owner)
{
if (!_windows.ContainsKey(type.Name))
{
_windows.Add(type.Name, new WinEntity { Type = type, Owner = owner });
}
}
public static bool ShowDialog(string winKey,object dataContext)
{
if (_windows.ContainsKey(winKey))
{
Type type = _windows[winKey].Type;
var win = (Window)Activator.CreateInstance(type);
win.DataContext = dataContext;
win.Owner = _windows[winKey].Owner;
return win.ShowDialog() == true;
}
return false;
}
}
public class WinEntity
{
public Type Type { get; set; }
public Window Owner { get; set; }
}
注册
绑定
执行
internal class ViewModel
{
public Model model { get; set; } = new Model();
public CommandBase Btn1 { get; set; }
public CommandBase Btn2 { get; set; }
public ViewModel()
{
Btn1 = new CommandBase()
{
DoExecute=new Action<object>(Funtion1),
DoCanExecute=new Func<object, bool>(CanFuntion1)
};
Btn2 = new CommandBase()
{
DoExecute = new Action<object>(Funtion2),
DoCanExecute = new Func<object, bool>(CanFuntion2)
};
}
public void Funtion1(object obj)
{
//第一种
ViewModel viewmodel = new ViewModel();
viewmodel.model.Value1 = 123;
if (WindowManager.ShowDialog("SubWindow", viewmodel))
{
}
else
{
}
}
public bool CanFuntion1(object obj)
{
return this.model.Value1 != 0;//条件判断,按钮是否可用
}
public void Funtion2(object obj)
{
//WindowManager.Register(typeof(SubWindow))
}
public bool CanFuntion2(object obj)
{
return this.model.Value3 != 0;
}
}