MVVM
简单的说:MVVM实际上是三层架构,M层(Model实体层)、V层(View表示层,它有DataContext属性,这个属性可以使用DataTemplate模板绑定VM层的数据用来显示)、VM层(ViewModel层,对Model层进行CRUD进行操作,同时对V层提供数据绑定)
- 采用mvvm的好处:项目可测试更高,从而可以执行单元测试;将UI和业务的设计完全分开,View和UnitTest只是ViewModel的两个不同形式的消费者
- Model的职责:主要提供基础实体的属性以及每个属性的验证逻辑;不包含数据的调用;不依赖于任何项目。
- ViewModel:
ViewModel是MVVM架构中最重要的部分,ViewModel中包含属性,命令,方法,事件,属性验证等逻辑。为了与View以及Model更好的交互来满足MVVM架构,ViewModel的设计需要注意一些事项或者约束:
ViewModel的属性:ViewModel的属性是View数据的来源。这些属性可由三部分组成:
一部分是Model的复制属性。
另一部分用于控制UI状态。例如一个弹出窗口的控件可能有一个IsClose的属性,当操作完成时可以通过这个属性更改通知View做相应的UI变换或者后面提到的事件通知。
第三部分是一些方法的参数,可以将这些方法的参数设置成相应的属性绑定到View中的某个控件,然后在执行方法的时候获取这些属性,所以一般方法不含参数。
ViewModel的命令:ViewModel中的命令用于接受View的用户输入,并做相应的处理。我们也可以通过方法实现相同的功能。
ViewModel的事件: ViewModel中的事件主要用来通知View做相应的UI变换。它一般在一个处理完成之后触发,随后需要View做出相应的非业务的操作。所以一般ViewModel中的事件的订阅者只是View,除非其他自定义的非View类之间的交互。
ViewModel的方法:有些事件是没有直接提供命令调用的,如自定义的事件。这时候我们可以通过CallMethodAction来调用ViewModel中的方法来完成相应的操作。
View Model一般有以下三个部分组成
1、属性:一个事物,它的类型可以是一个字符型,也可以是一个对象。实现接口INotifyPropertyChanged,那么任何UI元素绑定到这个属性,不管这个属性什么时候改变都能自动和UI层交互。
2、集合:事物的集合,它的类型一般是ObservableCollection,因此,任何UI元素绑定到它,不管这个集合什么时候改变,都可以自动的与UI交互。
3、Commands:一个可以被触发的事件,并且可以传递一个类型为Object的参数。但是前提是要实现接口ICommand。
主要有以下三个部分组成
1、把View Model层的属性绑定到 text box, radio button, toggle button, MediaElement, trigger an animation or ViewState change
2、把View Model层的集合绑定到ListBox,TreeView,DataGrid
3、Commands
使用InvokeCommandAction实现以下behavior
A、绑定View Model层的ICommand
B、指出你需要实现的ICommand(比如Click事件,Selected事件。。。)
C、传递参数
MVVM的简单实例
XAML代码
<Window x:Class="DeepXAML.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:DeepXAML" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:cl="clr-namespace:System.Collections;assembly=mscorlib" Title="MainWindow" Height="250" Width="450"> <StackPanel> <TextBox Text="{Binding Path=Name}"></TextBox> <TextBox Text="{Binding Path=Age}"></TextBox> <Button Command="{Binding Path=AddAge}" >Add Age</Button> </StackPanel> </Window>
MainPageViewModel
public class MainPageViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private string name; public string Name { get { return name; } set { name = value; if (this.PropertyChanged != null) { this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name")); } } } private int age; public int Age { get { return age; } set { age = value; if (this.PropertyChanged != null) { this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Age")); } } } public ICommand AddAge { get { return new AddAgeCommand(this); } } }
public class AddAgeCommand : ICommand { private MainPageViewModel mMainPageViewModel; public AddAgeCommand(MainPageViewModel model) { mMainPageViewModel = model; } public bool CanExecute(object parameter) { return true; } public event EventHandler CanExecuteChanged; public void Execute(object parameter) { this.mMainPageViewModel.Age += 1; } }
我们可以看一下后台只有很少代码:
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); MainPageViewModel mainPageViewModel = new MainPageViewModel { Age = 20, Name = "Jack" }; this.DataContext = mainPageViewModel; } }