1. MVVM模式简要介绍
完整一些应该是Model-View-ViewModel,即分为这三个部分。
(1)Model:后台数据和业务逻辑相关。目前我认知就是创建一个类,里面写业务相关的数据类型。
(2)View:用户看到和交互的视图,XAML中绘制的。不涉及业务相关。
(3)ViewModel:沟通Model和View的,反映界面的状态、流程和运行逻辑。
2. 最简单的示例实现(学生信息)
(1)创建Model类
里面创建业务相关的数据类型,比如MyStudent类。
class MyStudent
{
public MyStudent() { }
public string? Name { get; set; }
public int? ID { get; set; }
public string? Phone { get; set; }
}
(2)创建View
里面用XAML实现用户界面,比如“添加”和“移除”两个按钮。
在XAML中创建了Button之后,需要绑定其点击事件(用Winform方式就是Click="Func",然后在函数中实现即可,即事件驱动)。用WPF的数据驱动方式,则是编写其Command属性,绑定ViewModel中的函数对象。先把这块代码贴出来:
A. Button部分
<Button Content="Add" Width="120" Command="{Binding BtnClick_Add}" Style="{StaticResource BtnStyle}"/>
<Button Content="Remove" Width="120" Command="{Binding BtnClick_Remove}" Style="{StaticResource BtnStyle}"/>
<Button Content="Modify" Width="120" Command="{Binding BtnClick_Modify}" Style="{StaticResource BtnStyle}"/>
B. TextBox部分
<TextBlock Grid.Row="0" Grid.Column="0" Text="Name: " HorizontalAlignment="Right" VerticalAlignment="Center" />
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding VM_Name}" HorizontalAlignment="Center" VerticalAlignment="Center" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="ID: " HorizontalAlignment="Right" VerticalAlignment="Center" />
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding VM_ID}" HorizontalAlignment="Center" VerticalAlignment="Center" />
<TextBlock Grid.Row="2" Grid.Column="0" Text="Phone: " HorizontalAlignment="Right" VerticalAlignment="Center" />
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding VM_Phone}" HorizontalAlignment="Center" VerticalAlignment="Center" />
当然,在能够识别之前,需要关联数据上下文DataContext到ViewModel中。即在界面的定义部分添加代码:
xmlns:VM="clr-namespace:LeadlapAPCDemo.ViewModel"
d:DataContext="{d:DesignInstance Type=VM:MainWindowViewModel}"
(3)创建ViewModel类
A. 首先确保项目中已经添加了MVVM的程序包。
B. 引用库:
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
C. ViewModel类要继承ObservableObject。
D. 创建属性,以和View中欲修改的变量对应。
private string? _VM_Name;
private long _VM_ID;
private string? _VM_Phone;
public string? VM_Name
{
get => _VM_Name;
set => SetProperty(ref _VM_Name, value);
}
public long VM_ID
{
get => _VM_ID;
set => SetProperty(ref _VM_ID, value);
}
public string? VM_Phone
{
get => _VM_Phone;
set => SetProperty(ref _VM_Phone, value);
}
这样如果属性值发生变化,会触发Set,进而通过SetProperty触发了里面封装OnPropertyChanged(ObservableObject已经封装好了),便将值更新到View中。
E. 声明按钮事件对应的Command,并在适当地方(比如ViewModel的构造函数中)实例化,传入定义的功能函数对象。
public RelayCommand BtnClick_Add { get; }
public RelayCommand<object> BtnClick_Remove { get; }
public RelayCommand<object> BtnClick_Modify { get; }
public TestViewModel()
{
BtnClick_Add = new RelayCommand(VM_Add);
BtnClick_Remove = new RelayCommand<object>(VM_Remove);
BtnClick_Modify = new RelayCommand<object>(VM_Modify);
}
void VM_Add()
{
//具体实现
MyStudent student = new MyStudent();
student.Name = VM_Name;
student.ID = VM_ID;
student.Phone = VM_Phone;
mStudentList.Add(student);
}
void VM_Remove(object? sender)
{
//具体实现
}
void VM_Modify(object? sender)
{
//具体实现
VM_Name = "XiaoHong";
VM_ID -= 1;
}
这样基本可以看到一点效果了。
3. 测试
点击Modify,界面同步修改刷新了。
例子记录自己的学习过程,对于该实例显得有些“大费周章”,但是对于一些复杂项目,这种数据驱动、前后端分离的方式还是便捷合理的。