MVVM模式
1.原理
基于数据绑定和命令模式实现:
- 数据绑定:视图和视图模型之间通过数据绑定来实现交互。当视图模型中的数据发生变化时,视图会自动更新相应的内容,从而实现了视图和视图模型之间的数据同步。
- 命令模式:视图和视图模型之间通过命令模式来实现交互。视图中的用户交互事件会被转换为命令,然后传递给视图模型进行处理。
MVVM架构的核心在于将视图和模型完全解耦,视图只负责渲染用户界面,而视图模型负责处理业务逻辑和数据操作。视图和视图模型之间通过数据绑定和命令模式进行交互,从而实现了解耦和职责分离。
2.代码解析
实例场景:两个输入值,计算他们的和,得到一个结果
ViewModel基类:
namespace WpfApp1.ViewModels
{
class NotificationObject : INotifyPropertyChanged
{
//ViewModel的某个属性借助Binding关联到View上的控件属性
//Binding会侦听该事件的发生(属性值更改时发生),并把改变后的属性值发送到界面
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if(this.PropertyChanged!=null)
{
//触发属性更改事件
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
ViewModel类:
namespace WpfApp1.ViewModels
{
class MainWindowViewModel:NotificationObject
{
private double input1;
//Binding可以传递控件属性到后台,但是属性值改变必须通过RaisePropertyChanged才能通知到前台
public double Input1
{
get { return input1; }
set{
input1 = value;
this.RaisePropertyChanged("Input1");
}
}
private double input2;
public double Input2
{
get { return input2; }
set
{
input2 = value;
this.RaisePropertyChanged("Input2");
}
}
private double result;
public double Result
{
get { return result; }
set
{
result = value;
this.RaisePropertyChanged("Result");
}
}
public DelegateCommand AddCommand { get; set; }
public MainWindowViewModel()
{
//初始化命令
this.AddCommand = new DelegateCommand(Add);
}
private void Add(object paramater)
{
//属性值改变,触发set,通知binding
this.Result = Input1 + Input2;
}
}
}
CallerMemberName
改进:
//CallerMemberName:允许获取方法调用方的方法或属性名称。
public void RaisePropertyChanged([CallerMemberName]string propertyName="")
{
if(this.PropertyChanged!=null)
{
//触发属性更改事件
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
private double input1;
public double Input1
{
get { return input1; }
set{
input1 = value;
this.RaisePropertyChanged();//不需要指定属性名称
}
}
DelegateCommand类:
namespace WpfApp1.Command
{
class DelegateCommand : ICommand
{
public event EventHandler CanExecuteChanged;
Action<object> ExcuteAction { get; set; }
public Func<object, bool> CanExcuteFunc { get; set; }
public DelegateCommand(Action<object> action)
{
this.ExcuteAction=action;
}
public bool CanExecute(object parameter)
{
if (this.CanExcuteFunc == null)
return true;
return this.CanExcuteFunc(parameter);
}
//定义调用此命令时要调用的方法
public void Execute(object parameter)
{
if (ExcuteAction == null)
return;
//执行这个委托传递的方法
ExcuteAction(parameter);
}
}
}
扩展:上述Button为例,只有点击Click时才会触发命令发送,显然这是不够的,界面中除了点击行为以外,还有很多其他行为,诸如鼠标移入,鼠标移出,双击等等,可用使用Triggers绑定命令,如下:
<!--例子二: 普通控件内的使用-->
<Button
Content="ED Label"
FontSize="20"
Foreground="Pink">
<i:Interaction.Triggers>
<i:EventTrigger EventName="xxx">
<i:InvokeCommandAction Command="{Binding xxx}" CommandParameter="{Binding xxx}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律