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;
        }      
    }

相关推荐