MVVM设计模式
MVVM是Model、View、ViewModel的简写,这种模式的引入就是使用ViewModel来降低View和Model的耦合,说是降低View和Model的耦合。也可以说是是降低界面和逻辑的耦合,理想情况下界面和逻辑是完全分离的,单方面更改界面时不需要对逻辑代码改动,同样的逻辑代码更改时也不需要更改界面。同一个Model可以使用完全不用的View进行展示,同一个View也可以使用不同的Model以提供不同的操作。
各部分责任分析
- Model 负责数据和逻辑的处理,对于Model层,它什么也不知道
- ViewModel 将逻辑交由Model处理,并向外暴露数据,它只知道Model
- View 显示界面,并将数据变化通知ViewModel,它只知道ViewModel
WPF使用MVVM设计模式
在WPF的MVVM模式中,View和ViewModel之间数据和命令的关联都是通过绑定实现的,绑定后View和ViewModel并不产生直接的依赖。具体就是View中出现数据变化时会尝试修改绑定的目标。同样View执行命令时也会去寻找绑定的Command并执行。反过来,ViewModel在Property发生改变时会发个通知说“名字叫XXX的Property改变了,你们这些View中谁绑定了XXX也要跟着变啊!”,至于有没有View收到是不是做出变化也不关心。ViewModel中的Command脱离View就更简单了,因为Command在执行操作过程中操作数据时,根本不需要操作View中的数据,只需要操作ViewModel中的Property就可以了,Property的变化通过绑定就可以反映到View上。这样在测试Command时也不需要View的参与。
待解决问题
- 数据绑定:View–>View; View–>ViewModel; ViewModel–>View
- 命令绑定与事件绑定:View–>ViewModel
数据绑定
View–>View
- XML绑定
DestinationProperty=”{Binding ElementName=SourceObjectName, Path=SourceProperty}”
- C#绑定
Binding binding = new Binding(); binding.Source = txtName;//设置源对象 binding.Path = new PropertyPath("Text");//设置源属性 tbShowMessage.SetBinding(TextBlock.TextProperty, binding);//添加到目标属性 //or //BindingOperations.SetBinding(tbShowMessage, TextBlock.TextProperty, binding);
对集合添加、删除等操作又需要使用数据绑定时要优先考虑ObservableCollection
View–>ViewModel
View由依赖属性实现属性改变通知的传递,但要注意传递属性改变的时间,比如TextBox在响应TextChanged事件时,还没有传递,而响应LostFocus时,已经传递
ViewModel–>View
ViewModel为了通知View数据的变化,必须借助INotifyPropertyChanged接口。
- 一般思路
class NotificationObject:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (null != PropertyChanged)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
class ViewModel:NotificationObject
{
private int _Age;
public int Age
{
get { return _Age; }
set
{
if(_Age != value) //防止通知死循环
{
_Age = value;
RaisePropertyChanged("Age");
}
}
}
...
}
命令绑定与事件绑定
命令绑定
class DelegateCommand:ICommand
{
public bool CanExecute(object parameter)
{
if(null != CanExecuteFunc)
CanExecuteFunc(parameter);
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
if(null != ExecuteAction)
ExecuteAction(parameter);
}
public Action<object> ExecuteAction{get;set;}
public Func<object,bool> CanExecuteFunc{get;set;}
}
class ViewModel:NotificationObject
{
public ViewModel()
{
...
OperCommand = new DelegateCommand();
OperCommand.ExecuteAction += Oper;
}
...
public DelegateCommand OperCommand{get;set;}
private void Oper(object parameter)
{
...
}
}
事件绑定(两种方式)
- 引入reference库
Microsoft.Expression.Interactions.dll
System.Windows.Interactivity.dll - XAML中加入引用
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
- 在ViewModel中加入Method和事件
public void Method()
{
...
}
public DelegateCommand OperCommand{get;set;}
- 绑定事件
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding OperCommand}" CommandParameter="{Binding ElementName=*}"/>
</i:EventTrigger>
<i:EventTrigger EventName="KeyUp">
<i:EventTrigger EventName="Click">
<ei:CallMethodAction TargetObject="{Binding}" MethodName="Method"/>
</i:EventTrigger>
</i:EventTrigger>
</i:Interaction.Triggers>
- MVVMLight使用
- ViewModelBase提供ViewModel的基类
- RelayCommand和RelayCommand
实现命令机制 - EventToCommand将任意事件绑定到命令
- Message(消息)机制,提供了一个Messenger类型,可以用来发送和接收消息,它还提供了默认的几种消息类型。可以注册消息用来接收处理,可以产生并发送消息[参考]