介绍
MVVMLight是一个实现MVVM模式的轻量级框架(相对于Prism),能够更好的帮助我们开发WPF Windows Phone、Windows 8、SilverLight相关项目。
安装
在NuGet 工具箱上搜索MVVMLight进行下载
下载后它帮你生成ViewModel文件夹,里面包含MainViewModel和ViewModelLocator文件,然后需要自己建立一个完整的架构目录。
当安装完成之后由于版本原因在ViewModelLocator文件中的using引用会报错进而导致程序无法执行,所以需要修改引用。
将报错的using Microsoft.Practices.ServiceLocation; 引用修改为using CommonServiceLocator;
分层架构
1、View负责前端展示,与ViewModel进行数据和命令的交互。
2、ViewModel,负责前端视图业务级别的逻辑结构组织,并将其反馈给前端。
3、Model,主要负责数据实体的结构处理,与ViewModel进行交互。
MVVMLight架构的使用
1.在Model写一个实体对象用于和ViewModel交互
在MVVMLight中使用ObservableObject类实现实时监听数据变更。
ObservableObject,这个父类的作用就是保证能够检测属性是否被改变。它实现了INotifyPropertyChanged接口,通过触发PropertyChanged事件达到通知UI更改的目的,所以我们在定义实体对象的时候,只需要调用RaisePropertyChanged(PropertyName)就可以进行属性更改通知了。
public class WelcomeModel : ObservableObject{private String introduction;public String Introduction{get { return introduction; }set { introduction = value; RaisePropertyChanged(()=>Introduction); }}}
2.写一个ViewModel用于和View交互
此类继承了ViewModelBase父类,ViewModelBase同时继承 ObservableObject类和ICleanup接口。所以他同样有INotifyPropertyChanged接口的能力,能够通过触发PropertyChanged事件达到通知View的目的;构造函数中对 Welcome 属性进行了实例化。
public class WelcomeViewModel:ViewModelBase{/// <summary>/// 构造函数/// </summary>public WelcomeViewModel(){Welcome = new WelcomeModel() { Introduction = "Hello World!" };}#region 属性private WelcomeModel welcome;/// <summary>/// 欢迎词属性/// </summary>public WelcomeModel Welcome{get { return welcome; }set { welcome = value; RaisePropertyChanged(()=>Welcome); }M1 = new RelayCommand(f1);// 给指令赋值}public RelayCommand M1 { get;set; }// 回调函数 无返回值public void f1(){MessageBox.Show("f1");}#endregion}
3.写一个View,来显示数据和交互ViewModel。
TextBlock 绑定了 Welcome.Introduction,所以应该显示Welcome对象下的Introduction属性。
<Window x:Class="MVVMLightDemo.View.WelcomeView"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="WelcomeView" Height="300" Width="300"><Grid><StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" ><TextBlock Text="{Binding Welcome.Introduction}" FontSize="30" ></TextBlock><Button Width="200" Command="{Binding M1}" Height="40">点击</Button></StackPanel></Grid></Window>把 WelcomeViewModel 赋值给当前视图的数据上下文。所以可以在当前视图中使用ViewModel中所有的公开属性和命令。using MVVMLightDemo.ViewModel;using System.Windows;namespace MVVMLightDemo.View{/// <summary>/// Interaction logic for WelcomeView.xaml/// </summary>public partial class WelcomeView : Window{public WelcomeView(){InitializeComponent();this.DataContext = new WelcomeViewModel();}}}
构造器
所以每次App初始化的时候,就会去初始化ViewModelLocator类。
实际上他就是一个很基本的视图模型注入器。在构造器中把使用到的ViewModel统一注册,并生成单一实例。然后使用属性把它暴露出来,每当我们访问属性的时候,就会返回相应的ViewModel实例。
第一步在APP.xaml中添加引用
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" /><Application x:Class="MVVMLightDemo.App"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"StartupUri="View/WelcomeView.xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"d1p1:Ignorable="d"xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:vm="clr-namespace:MVVMLightDemo.ViewModel" ><Application.Resources><ResourceDictionary><vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" /></ResourceDictionary></Application.Resources></Application>
第二步在ViewModelLocator类中注册对象并且实例化
下文中实例化的MainViewModel就是用于和View交互ViewModel中的类
namespace MVVMLightDemo.ViewModel{public class ViewModelLocator{/// <summary>/// Initializes a new instance of the ViewModelLocator class./// </summary>public ViewModelLocator(){ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);// 1.先注册对应的vm对象SimpleIoc.Default.Register<MainViewModel>();}// 2.实例化#region 实例化public MainViewModel Main{get{return ServiceLocator.Current.GetInstance<MainViewModel>();}}#endregionpublic static void Cleanup(){// TODO Clear the ViewModels}}}
第三步在xaml中绑定
DataContext="{Binding Source= {StaticResource Locator},Path=Main}"
我们可以将后台CS中的 this.DataContext = new WelcomeViewModel(); 可以去掉了,直接在WelcomeView中这样写:
DataContext="{Binding Source={StaticResource Locator},Path=Welcome}",
这种写法当我们绑定到数据,编译之后就会立马呈现
服务端开发人员可以专心写ViewModel的业务逻辑代码,UI开发人员可以专注设计视图了,同样 ViewModel可以绑定到不同的视图上,所以从这边就可以体现出他其中的三个重要特性:低耦合、可重用性、独立开发。 ViewModelLocator 类中还有个 ClearnUp()方法,主要目的用来清除ViewModel实例的。ViewModelBase继承了GalaSoft.MvvmLight.ICleanup接口,并在自己的类中写好了Cleanup()虚方法。所以我们在实例ViewModel类中可以重写Cleanup()来达到清除当前实例的目的。
伟大的双向绑定
场景: 当数据发生变化时 数据源跟着发生变化 进而触发数据更新,另一条绑定数据源的数据也会跟着发生变化
下文中UpdateSourceTrigger属性的作用是 当做何种改变的时候通知数据源我们做了改变。
<StackPanel Orientation="Vertical" Margin="10,10,0,0"><StackPanel Margin="0,10,0,0" Orientation="Horizontal" ><TextBlock Text="Hello " ></TextBlock><TextBlock Text="{Binding UserInfo.UserName}" ></TextBlock></StackPanel><StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal" ></StackPanel></StackPanel>
(当修改输入框的内容的时候,对应绑定数据相应改变,并触发对UI的修改,所以下面那行文字也相应改变改变。)
UpdateSourceTrigger属性:
枚举类型 | 效果 |
Default | 默认值(默认为LostFocuse) |
Explicit | 当应用程序调用 UpdateSource 方法时生效 |
LostFocus | 失去焦点的时候触发 |
PropertyChanged | 数据属性改变的时候触发 |
这边我们直接使用 PropertyChanged,当UI数据改变的时候,我们再通知到数据源去做修改。
还有一个属性就是Mode,他有五个参数:
枚举类型 | 效果 |
OneWay | 源发生变化,数据就会从源流向目标 |
OneTime | 绑定会将数据从源发送到目标;但是,仅当启动了应用程序或 DataContext 发生更改时才会如此操作,因此,它不会侦听源中的更改通知。 |
OneWayToSource | 绑定会将数据从目标发送到源 |
TwoWay | 绑定会将源数据发送到目标,但如果目标属性的值发生变化,则会将它们发回给源 |
Default | 绑定的模式根据实际情况来定,如果是可编辑的就是TwoWay,只读的就是OneWay |
这边明显有很多种选择,明确一点的是,我们是想把View上的变化同步到ViewModel(Target => Source),所以使用OneWayToSource、TwoWay、Default或者不写都可以。严谨点应该使用OneWayToSource。因为是文本框,属于可以编辑控件,所以 Default指向的是TwoWay。下面还有一个TextBlock,仅仅用于显示的,所以不需要目标对源的修改,无需指定就默认是OneWay,当源改变的时候,会通知它进行修改。
MVVMLight架构详细介绍学习网站
https://www.cnblogs.com/wzh2010/category/937606.html