- 浏览: 475742 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (1028)
- [发布至博客园首页] (826)
- [随笔分类]个人生活随笔 (14)
- [网站分类]首页候选区 (26)
- [网站分类]SharePoint (15)
- [网站分类]其他技术区 (6)
- [随笔分类]批处理技巧 (6)
- [随笔分类].net 2.0 (3)
- [随笔分类]SharePoint2007(MOSS2007) (0)
- [网站分类].NET新手区 (6)
- [网站分类]ASP.NET (6)
- [网站分类]架构设计 (18)
- [网站分类]程序人生 (2)
- [网站分类]SQL Server (2)
- WCF (3)
- 编程技巧 (2)
- 模式架构 (2)
- 分析设计 (4)
- 生活随笔 (0)
- 软件工程 (1)
- Android实例 (2)
最新评论
-
zilong0536:
楼主您好:
请问发表博文支持图片的功能怎么实现啊,一直没有思路 ...
新浪微博开放平台开发-android客户端(3) -
nicegege:
小弟 学习了
帮助中国移动设计10086的排队小模块 -
zl7824516:
用什么技术没说啊
通告(公告),消息(站内短信),提醒的设计:通告 -
virusswb:
源码下载: SinaWeibo2 源码下载之后,将后缀改为ra ...
新浪微博开放平台开发-android客户端(3) -
Jimmyxu0311:
找不到源码下载
新浪微博开放平台开发-android客户端(3)
[Translation]Silverlight 4-MVVM with Commanding and WCF RIA Services
- 博客分类:
- [发布至博客园首页]
原文地址:Silverlight 4 - MVVM with Commanding and WCF RIA Services
在我的前一篇文章 “WCF RIA Services and a guide to use DTO/”Presentation Model””,我提到要写一篇文章来讲述ViewModel。在这篇文章中,我将向你展示如何利用Silverlight 4 Commanding 和ViewModel来实现MVVM模式。在文章中我将使用Unity作为依赖注入框架将我的Repository注入DomainService,为了达到目的,我们需要创建自己的DomainServiceFactory,在我的“WCF RIA Services Unity DomainServiceFactory” 中你将会学到如何使用Unity和依赖注入,在本文章中就不再多说。
架构和设计
下图显示的是我经常在建立RIA应用的时候使用的架构和设计。
本文的服务层使用WCF RIA Service的DomainService,Domain Model将会非常简单,只是一个Customer实体和一个CustomerRepository。下图是Customer的类图
下面是CustomerRepository的接口代码
{
Customer GetCustomerByID(int customerID);
void Update(Customer customer);
}
注意:本文的重点不是如何实现ICustomerRepository接口,这里假设使用Entity Framework,Linq to SQL或者NHibernate、ADO.NET都可以。这些不是本文的重点。
下面的代码是使用了WCF RIA Services的DomainService,ICustomerRepository应该被注入。
public class CustomerService : DomainService
{
private ICustomerRepository _customerRepository;
public CustomerService(ICustomerRepository customerRepository)
{
_customerRepository = customerRepository;
}
public CustomerDto GetCustomerByID(int customerID)
{
var customer = _customerRepository.GetCustomerByID(customerID);
return MapCustomerToCustomerDto(customer);
}
public void UpdateCustomer(CustomerDto customer)
{
if (customerDto == null)
throw new ArgumentNullException("customer");
_customerRepository.Update(MapCustomerDtoToCustomer(customerDto));
}
}
你可能已经发现了,在domain 实体Customer和CustomerDto(Data Transfer Object)之间有一个映射。如果我们使用过WCF,我们就会将对象实体映射为数据契约。在这里使用了类似AutoMapper 的框架来帮助我们代替手工映射。在内网应用中,网速良好,没有太复杂的业务逻辑的情况下,我们可以在不进行映射的情况下直接使用Customer实体。但是这些都依赖于我们构建的应用,在我们作出正确决定之前,已经有很多因素被包含进来。因此,本文也不是银弹。下面是CustomerDto的代码,在里面使用了一些验证规则,如果使用ViewModel,这些代码应该放入ViewModel中。
{
[Key]
public int CustomerID { get; set; }
[Required]
[StringLength(32, MinimumLength=2)]
public string FirstName { get; set; }
[Required]
[StringLength(32, MinimumLength = 2)]
public string LastName { get; set; }
public int Age { get; set; }
}
注意:我将会使用自己的DomainServiceFactory在创建CustomerService的时候注入ICustomerRepository,可以通过阅读here. 来指导更多相关知识。
现在服务层已经完成,继续来实现client端,将会使用ViewModel和Silverlight4的Commanding。
ViewModel
一个ViewModel就是View的一个代理类。想像一下电影《矩阵》,我们只看见屏幕上面的一些字符,通过这些字符我们看见了世界。可以将ViewModel想象成字符,通过他们我们可以看见View。使用ViewModel的原因是分离关注,我们不想在View中看见逻辑代码。使用这种分离,即使UI还没有摆放好的时候,我们也可以通过自动化测试来测试View。
下面是一段ViewModel代码,使用了Commanding
{
public CustomerViewModel()
{
}
public string FirstName
{
get;
set;
}
public string LastName
{
get;
set;
}
public bool IsAdult
{
get;
}
{
get;
}
}
ViewModel代表了一个应该显示两个输入框的View,一个是firstname,一个是lastname,和一个代表Customer是否audit的只读checkbox。View还应该由一个Save按钮。IsLoading用来显示或者隐藏进度条。这里View将会使用ViewModel
下面是View的xaml代码,不需要后台代码,只需要将ViewModel作为资源加入,将数据绑定到ViewModel。
xmlns:my="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit" x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:SilverlightApplication1.ViewModels"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<vm:CustomerViewModel x:Name="customerViewModel"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" DataContext="{StaticResource customerViewModel}">
<my:BusyIndicator IsBusy="{Binding IsLoading}"></my:BusyIndicator>
<TextBox Text="{Binding FirstName, Mode=TwoWay, NotifyOnValidationError=True}" ... />
<TextBox Text="{Binding LastNaem, Mode=TwoWay, NotifyOnValidationError=True}" ... />
<TextBlock Text="First Name:" .../>
<TextBlock Text="Last Name:" .../>
<CheckBox IsChecked="{Binding IsAdult}" Content="Is Adult" .../>
<Button Command="{Binding Save}" Content="Save" ... />
</Grid>
</UserControl>
ViewModel的实现代码
你会发现CustomerViewModel继承自ViewModel,ViewModel实现乐INotifyPropertyChanged和INotifyDataErrorInfo接口。你可以在ViewModel on my other post about INotifyDataErrorInfo class. 中找到具体的实现。在CustomerViewModel的构造函数中调用WCF RIA Services来获取一个Customer,因为操作是异步的,我们不知道多长时间可以有结果,因此将IsLoading属性设置为true显示正在加载,下面是实现的代码。
{
CustomerContext _customerContext = new CustomerContext();
CustomerDto _customerDto = new CustomerDto();
bool _isLoading = false;
public CustomerViewModel()
{
this.IsLoading = true;
_customerContext.Load<CustomerDto>( _customerContext.GetCustomerByIDQuery(10),
loadOperation =>
{
_customerDto = loadOperation.Entities.SingleOrDefault();
LoadingCompleted();
}, null);
}
public string FirstName
{
get { return _customerDto.FirstName; }
set
{
if (_customerDto.FirstName != value)
{
_customerDto.FirstName = value;
NotifyPropertyChanged("FirstName");
}
}
}
public string LastName
{
get { return _customerDto.LastName; }
set
{
if (_customerDto.LastName != value)
{
_customerDto.LastName = value;
NotifyPropertyChanged("LastName");
}
}
}
public bool IsLoading
{
get { return _isLoading; }
internal set { _isLoading = value; NotifyPropertyChanged("IsLoading"); }
}
public bool IsAdult
{
get { return _customerDto.Age >= 18; }
}
public ICommand Save
{
get { return new SaveCommand(this); }
}
internal void SaveCustomer()
{
_customerContext.SubmitChanges();
} private void LoadingCompleted() { NotifyPropertyChanged("FirstName"); NotifyPropertyChanged("LastName"); NotifyPropertyChanged("IsAdult"); this.IsLoading = false; }
}
看起来可能有点奇怪,一个空的CustomerDto被分配给_CustoemrDto字段。CustoemrViewModel的其他属性将会访问这个字段和他的属性,为了避免在get和set中添加一大丢检查是否null的代码,使用了一个默认的CustomerDto。因此,虽然有点丑陋,但是在每个属性中避免了一大丢代码。在构造函数中将会加载一个Customer。
{
this.IsLoading = true;
_customerContext.Load<CustomerDto>(
_customerContext.GetCustomerByIDQuery(10),
loadOperation =>
{
_customerDto = loadOperation.Entities.SingleOrDefault();
LoadingCompleted();
}, null);
}
IsLoading属性设置为true,可以保证加载数据的时候显示进度条。当Customer对象加载完毕,_CustomerDto会设置为加载的customer对象,将会调用LoadingCompleted方法。方法将会保证隐藏进度条,通知View变化,因此控件绑定将会调用绑定属性的get方法显示customer的内容。
Commanding
你可以从“Silverlight 4 Commanding enables ViewModels”. 中阅读一些关于Commanding的知识。在ViewModel中有一个方法SaveRule,是CustomerViewModel实现了ISaveableViewModel 接口。CustomerViewModel中的Save属性可以返回一个SaveCommand。
public ICommand Save
{
get { return new SaveCommand(this); }
}
internal void SaveRule()
{
_customerContext.SubmitChanges();
}
Save属性绑定了View的Save按钮的command属性,下面就是Save属性返回的SaveCommand实现代码
{
private ISaveableViewModel _view;
public SaveCommand(ISaveableViewModel view)
{
_view = view;
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_view.SaveRule();
}
}
在SaveCommand中使用了一个ISaveableViewModel接口。保证加入ViewModel的Command会被执行,Command可以被其他View重用。
总结:
本文向你展示了如何使用WCF RIA Services,Model View View Model模式以及Commanding。代码可能不是最好的,没有加入更多的错误验证。
发表评论
-
NET 应用架构指导 V2 学习笔记(十六) 服务层设计指导
2010-06-04 00:13 527如果你的应用是通 ... -
NET 应用架构指导 V2 学习笔记(十七) 组件设计指导
2010-06-05 00:48 628组件提供了一种将 ... -
NET 应用架构指导 V2 学习笔记(十八) 表现层组件设计指导
2010-06-05 21:09 498本章讲述的是你在设计用户界面组件和表现层逻辑组件的时候应该 ... -
NET 应用架构指导 V2 学习笔记(十九) 表现层组件设计指导
2010-06-06 06:15 5605 决定数据绑定的 ... -
NET 应用架构指导 V2 学习笔记(二十) 业务组件设计指导
2010-06-07 06:58 581前言 业务组件 ... -
微软企业库5.0学习笔记(四十二)异常处理模块
2010-06-14 00:04 808企业库的异常处理 ... -
关于程序员在30岁、35岁之后怎么办的新思考
2010-06-14 10:40 598首先给大家问个好 ... -
NET 应用架构指导 V2 学习笔记(二十四) 跨层关注问题
2010-06-17 20:00 553概况 大部分的 ... -
微软企业库5.0学习笔记(四十三)数据验证模块
2010-06-19 08:07 967概况 任何接受用户或者是其他系统输入的应用,一定要确保 ... -
关于项目进度慢的思考----如何提高整体开发效率
2010-06-21 23:42 774我们都是软件行业 ... -
微软企业库5.0学习笔记(四十四)实战数据验证模块
2010-06-23 19:22 7971 在业务对象上添加验证 添加对程序集【Microso ... -
微软企业库5.0学习笔记(四十五)实战数据验证模块----高级篇
2010-06-24 19:41 9511、添加自定义的提示信息 验证失败的提示信息可以自定义 ... -
面向对象类设计的五大原则(一)单一职责原则Single Responsibility Principle
2010-06-29 15:45 739引言 面向对象类设计,或者说是面向对象设计,有五大原则 ... -
《深入浅出设计模式-中文版》读书笔记 开篇乱弹(一)
2010-07-01 06:42 624oreilly的《Head.First ... -
《深入浅出设计模式-中文版》读书笔记-继承与组合(三)
2010-07-03 16:53 581经过上一次的改造 ... -
《深入浅出设计模式-中文版》读书笔记-观察者模式(四)
2010-07-06 06:34 605今天要接触的是观 ... -
利用attribute实现简单的ORM
2010-07-09 15:27 649我不知道NH的ORM具 ... -
系统内部模块(子系统)之间的耦合以及模块(子系统)划分
2010-07-14 13:02 790题外话 最近已经在努力学习了,学习基本功,学习设计模式 ... -
《深入浅出设计模式-中文版》读书笔记-工厂模式(五)
2010-07-16 12:46 671今天给大家带来的是:工厂模式。 我们在代码中创建一个对 ... -
Head.First.Object-Oriented.Design.and.Analysis《深入浅出面向对象的分析与设计》读书笔记(一)
2010-07-18 21:47 640题外话 又是一本Head.First系列的书,这个系列 ...
相关推荐
Silverlight 4 in Action - Silverlight 4, MVVM, and WCF RIA Services
一个简单的 Silverlight 4 应用程序(MEF+ MVVM+ WCF RIA Services)配套源代码及安装文件 本文是Weidong Shen先生在CodeProject上的文章源代码
c#-的WPF---MVVM例子,大家共同学习
DEMO1-MVVM+RIA Service
WCF RIA Services+Mef+MVVM实现CRUD示例源码 实现了雇员的增删改查,雇员表(Employee)和部门表(Department)、雇员类型表 (EmployeeType)有外键关联,并和字典表(DataDict)有字典关系 示例采用技术说明: 1、...
A reference project that demonstrate how to build a task management application with WCF RiaServices, Silverlight 4.0, MEF, MVVM, and Telerik Controls. Requirement: VS2010, Silverlight 4 RTM, ...
一个简单的WPF程序
However, the knowledge of how to do this is missing from a large part of the development community―even amongst those who work with WPF and Silverlight on a daily basis. Too often there is a reliance...
mvvm wpf silverlight 设计模式
T-MVVM.zip,艺术帮是一款艺术图片应用,采用LiveData ViewModel RxJava okHttp Retrofit Glide架构的项目,仅用于学习交流,不断完善中。
Pro WPF and Silverlight MVVM - Effective Application Development with MVVM 非常好的介绍MVVM架构的书,是英文版原版的,特点是比较薄,有相当一部分代码页,容易看完,目录如下: Chapter 1: Overview of WPF...
使用Silverlight和Model-View-ViewModel模式写的简单小示例程序.
dotnet-communitytoolkit-mvvm
silverlight4+mvvm+RIAService搭建的一个小型的学习型demo,方便广大初学者学习和研究!
WPF-MVVM WPF MVVM模式开发的例子程序
DESCRIPTION Silverlight gives you entirely new ways to create rich internet applications, and now Silverlight 4 adds many ... * Building with WCF RIA Services * Out-of-browser, COM and Custom Chrome
MIX10-MVVM-Samples 支持wpf、silverlight、windows phone 7
WPF-MVVM实现CRUD操作
generator-mvvm-kotlin.zip,《MVVM With Kotlin》脚手架工具 An Kotlin MVVM Boilerplate for Android to save me having to create the same project over from scratch every time! :)
MVC-MVP-MVVM实例