MVVM在系统中如何应用实现
MVVM在TOPWELL中的应用
MVVM概念
MVVM严格来说,并不是一种框架,而是一个设计的模式。
MVVM即model(实体)+View(界面)+ViewModel(逻辑),model层负责建立数据实体,保障数据加载,是View中数据绑定的基本元素(但不是说View中去绑定Model实例)。View层不多说,强烈建议使用Microsoft Expression Blend进行界面设计,所有的数据展示及事件都采用绑定形式,这样设计人员就与开发人员彻底分离了。ViewModel层是联系View层与Model层的桥梁,View层所有的数据绑定都直接指向ViewModel。这里的model, View , ViewModel都是客户端silverlight应用,可以建立多个silverlight应用库项目已进行系统结构上的分割。
MVVM优点
MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model)。
- 1. 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
- 2. 可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
- 3. 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xaml代码。
- 4. 可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写
MVVM在TOPWELL的应用
首先开发环境要安装VS2012 然后再安装MVVMLIght Tookit 开发工具。
1.新建项目->Silverlight->MVVM->SimpleMVVMSilverlight
2.新的解决方案会生成一个MVVM架构的程序
3.MVVM架构的实现
1.Model
l 新建一个Models文件夹(如果项目里没有的话)当然在MVVMLight里已经创建好Model文件夹了。
l 创建一个Model类并且继承ModelBase<TModel>。
public class Customer : ModelBase[d1] <Customer>
l 用MVVMprop代码段插入支持双向的数据绑定的属性们。
public int CustomerId
{
get { return _customerId; }
set
{
_customerId = value;
NotifyPropertyChanged(m => m.CustomerId);[d2]
}
}
2.Service
创建一个服务代理接口里面包含的方法包括删除、修改、查询、插入(CRUD),把它放在
Services文件夹里。
public interface IItemListServiceAgent[d3]
{
// 查询
void GetItems(Action<List<Item>, Exception> completed);
// 插入
void AddItem(Item item);
// 删除
void RemoveItem(Item item);
// 保存
void SaveChanges(Action<Exception> completed);
// 撤销
void RejectChanges();
}
创建一个实现服务代理接口的类,把它添加到Services文件夹里。
[ServiceAgentExport(typeof(IItemListServiceAgent), AgentType = AgentType.Mock)]
public class MockItemListServiceAgent [d4] : IItemListServiceAgent
{
// 模拟数据
List<Item> mockItems = MockItems.GetItems();
// 查询
public void GetItems(Action<List<Item>, Exception> completed)
{
var bw = new BackgroundWorker();
bw.DoWork += (s, ea) =>
{
Thread.Sleep(TimeSpan.FromSeconds(2));
ea.Result = mockItems;
};
bw.RunWorkerCompleted += (s, ea) =>
{
if (ea.Error != null)
completed(null, ea.Error);
else
completed((List<Item>)ea.Result, null);
};
bw.RunWorkerAsync();
}
// 插入
public void AddItem(Item item)
{
mockItems.Add(item);
}
//删除
public void RemoveItem(Item item)
{
mockItems.Remove(item);
}
// TODO: 实现保存
public void SaveChanges(Action<Exception> completed)
{
MessageBox.Show("SaveChanges not implemented");
}
// TODO: 实现撤销
public void RejectChanges()
{
MessageBox.Show("RejectChanges not implemented");
}
}
3.ViewModel
新建一个类派生于ViewModelBase<TViewModel>或ViewModelDetailBase
<TViewModel, TModel>到ViewModels文件夹里。
l 把服务接口代理给构造函数
l 调用服务代理的方法来执行CRUD操作
l 也可以添加一个绑定的属性
public class CustomerViewModel [d5] : ViewModelDetailBase<CustomerViewModel, Customer>
{
// 构造函数
public CustomerViewModel() { }
//定义服务代理接口
ICustomerServiceAgent serviceAgent;
public CustomerViewModel(ICustomerServiceAgent serviceAgent)
{
this.serviceAgent = serviceAgent;
}
//数据集
private ObservableCollection[d6] < Customer > items;
public ObservableCollection< Customer > Items
{
get { return items; }
set
{
items = value;
NotifyPropertyChanged(m => m.Items);
}
}
// 显示层要绑定的方法
public void NewCustomer()
{
base.Model = serviceAgent.CreateCustomer();
}
}
4.Locator
用MvvMLocator代码段来添加需要代理的ViewModels到Locators文件夹。
public class ViewModelLocator[d7]
{
// 根据需求创建CustomerViewModel
public CustomerViewModel CustomerViewModel
{
get
{
ICustomerServiceAgent serviceAgent = new MockCustomerServiceAgent();
return new CustomerViewModel(serviceAgent);
}
}
}
5.View
用Silverlight User Controls,Pages or Child Windows创建一个View到Views文件夹里。
首先要把静态资源里的Locators绑定到View里的DataContext
DataContext="{Binding Source={StaticResource Locator}, Path=CustomerViewModel}"
在View上的单个元素需要指定一个在ViewModel里的属性(绑定源设置到DataContext)
<TextBox Grid.Row="0" Grid.Column="1" Height="30"
Text="{Binding Path=Model.CustomerId}" />
<Button Content="New Customer" Grid.Row="3" Grid.ColumnSpan="2"
Height="30" Width="100">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:CallMethodAction
[d8] TargetObject="{Binding}"
MethodName="NewCustomer"[d9] />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
MVVM总结
- MVVMLight,它是一种MVVM的实现。自然它不是唯一的一种实现,但现在大家公认的是,它是比较好的一个实现。就我个人的体会来说,我用过微软提供的Prism中的MVVM特性,但老实说,可能Prism的目标太大了,所以在MVVM这个具体的点上,实在不是那么好用。
- 不是说Prism不好,它与MVVMLight严格来说,不是一个重量级的产品。MVVMLight专注与MVVM的实现,自然更加灵活。
- 用MVVM这种架构可以有效的分离表现层和功能层,增强它们之间的松散耦合性,使得美工人员和设计人员各自专注自己的领域,而且这种模式可以最大限度的开发表现层的东西,表现层的方式也可以用WPF、WP8来实现,是非常方便的架构。
[d1]using SimpleMvvmToolkit;
[d2]Model里必须添加该属性
[d3]服务代理接口
[d4]实现服务接口的类
[d5]ViewModel
[d6]用该集合的原因是成员发生改变后会自动通知系统
[d7]定位器
[d8]需要引用如下
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
[d9]NewCustomer是ViewModel里的方法NewCustomer()