silverlight 学习笔记 (四): MVVM+WCF Ria开发架构


在前两已经基本了解了silverlight的基本开发思路,其中在应用MVVM架构有很多不解,经过这两天学习才大致了解了一些。有几个初学者常犯得错误需要提醒

1、silverlight 是一个富客户端应用程序,silverlight应用程序会以xap包方式加载到客户端,既然是客户端应用程序那么就没法直接与后台数据库进行访问,这就需要用到Webservice,WCF,WCF RIA等技术实现客户端与服务器端的数据传输,所以放弃以前在些asp.net时直接写sql调用后台数据库吧!

2、silverlight 不支持DataTable,DataSet等数据集方式的数据传输,我们不得不使用实体数据集方式进行数据传输了,不过国外有牛人做了一个工具将datatable转化成xml传输到客户在再进一步将字符串转化成实体数据集供silverlight使用。有兴趣可以搜索Silverlight.DataSet,使用起来还是很方便的,对我们在一些无法确定实体类的情况下查询有很大帮助。

3、在silverlight 中应用MVVM时,其中Model+ViewModel+View都是silverlight客户端程序,它们直接可以相互引用,但别幻想着应用Web应用程序库,因为Web应用程序库在服务器端使用的

下面开始重点介绍的silverlight 中应用MVVM+WCF RIA的开发架构,由于只学了两天,没有太多时间深入,只能把目前了解到的记录下来

1、MVVM即model(实体)+View(界面)+ViewModel(逻辑),model层负责建立数据实体,保障数据加载,是View中数据绑定的基本元素(但不是说View中去绑定Model实例)。View层不多说,强烈建议使用Microsoft Expression Blend进行界面设计,所有的数据展示及事件都采用绑定形式,这样设计人员就与开发人员彻底分离了,具体实现见上节。ViewModel层是联系View层与Model层的桥梁,View层所有的数据绑定都直接指向ViewModel。这里的model,view,viewmodel都是客户端silverlight应用,可以建立多个silverlight应用库项目已进行系统结构上的分割。

2、silverlight的数据传输:以本人目前所了解的多数情况下都是采用WCF RIA方式,其优点google上了解吧。我之所以选择WCF RIA 是因为它比WCF 实现起来简单多了,而且由于RIA Link的存在,让我们客户端使用服务器端应用逻辑如同客户端一样,这样就解决了silverlight客户端与服务器端无法共享业务逻辑了,同时RIA Link 会在客户端生成服务器端的“影子代码”,让开发人员不再担心客户端与服务器端代码同步的问题了。

3、WCF RIA的设计:目前大多数网上查的资料都是在使用ado.net数据实体+Domain service方式,而我所了解的是ado.net 数据实体模型只支持MS SqlServer ,而对于oracle还需要再去下载一个odac for 11g 才行,痛苦啊!同时如果我们要从原有系统的wcf 服务提供数据 ,那就意味着要在Domain Service 中定义自己的CURD了。我索性直接采用自定义实体类+自定义Domain service方法了。

下面重点讲下步骤:

1、在解决方案中选择建立web应用程序库(service),注意如果该web应用程序与Silverlight的host不在一个项目则Silverlight 的host Web项目要引用该Web项目(service),同时修改Web.config,可参照Service项目下的web.config,否则会出现错误:远程服务器返回了错误: NotFound。在Web应用程序库中建立实体类,注意实体类中必须要有主键

 

public class Items { [Key] public string SItemCode { get; set; } public string SItemName { get; set; } }


 2、建立Domain Servcie类

[EnableClientAccess()] public class DomainService1 : DomainService { public List<Items> GetItems() { List<Items> items = new List<Items>(); for (int i = 1; i < 10; i++) { Items item = new Items(); item.SItemCode = "A" + i.ToString(); item.SItemName = "this is " + i.ToString(); items.Add(item); } return items; } [Update] public void UpdateData(Items item) { //可添加SQL进行数据库操作 string s = item.SItemName; } [Delete] public void DeleteData(Items item) { string s = item.SItemName; } [Insert] public void InsertData(Items item) { string s = item.SItemName; } }


在建立类时[EnableClientAccess()]标识将能指示该类将在RIA Link中映射到客户端,本例子中建立了4个公共方法,为了简便我没有加入sql进行数据库的访问,GetItems()是给客户端查询提供数据,UpdateData()用来更新数据,需要注意的是在该方法上指定了[Update]属性,这样客户端在实体数据发生变化后可以应用此方法更新数据库数据,如果没有指定数据更新方法在客户端数据发生变化后会出现错误。删除、和添加方法定义一样。

3、建立silverlight应用程序,在silverlight项目上应用RIA Link,方法是在silverlight项目属性上在WCF RIA服务链接选择我们前面建立的Web应用程序库项目,这样在编译项目项目后会在该silverlight项目中添加一个隐藏的文件夹Generated_Code,这个文件夹中的内容是由系统产生,是根据我们之前定义的Domain Service类建立的,其中包含了一个DomainContext类和Entity实体类,我们可以应用该文件夹下所有的类。

4、建立ViewModel,为了简单我暂不建立Model类,在ViewModel中可以使用Ria Link 产生的DomainContext类中的包含实体集合类

public EntitySet<Items> Items { get { return base.EntityContainer.GetEntitySet<Items>(); } }

同时在该DomainContext会建立一个根据DomainService1 类中建立的数据查询方法

public EntityQuery<Items> GetItemsQuery() { this.ValidateMethod("GetItemsQuery", null); return base.CreateQuery<Items>("GetItems", null, false, true); }


在ViewModel中定义属性及事件

public class ItemViewModel:INotifyPropertyChanged { DomainService1 server = new DomainService1(); private Items _seletedItem = new Items(); public Items SeletedItem { get { return _seletedItem; } set { if (value != _seletedItem) { _seletedItem = value; PropertyChanged(this, new PropertyChangedEventArgs("SeletedItem")); } } } //private EntityQuery<Items> _itemList = new EntityQuery<Items>(); public EntitySet<Items> ItemList { get { return server.Items; } } public ICommand OnLoad { get { return new DelegateCommand(LoadData); } } private void LoadData(object obj) { EntityQuery<Items> list = server.GetItemsQuery(); LoadOperation<Items> loadOp = server.Load(list); // loadOp.Completed += new EventHandler(loadOp_Completed); } void loadOp_Completed(object sender, EventArgs e) { foreach (Items item in server.Items) { Items u = new Items(); u.SItemCode = item.SItemCode; u.SItemName = item.SItemName; //ItemList.Add(u); } } public ICommand OnUpdate { get { return new DelegateCommand(UpdateData); } } private void UpdateData(object obj) { server.SubmitChanges(); } public ICommand OnDelete { get { return new DelegateCommand(DeleteData); } } private void DeleteData(object obj) { server.Items.Remove(this.SeletedItem); server.SubmitChanges(); } public ICommand OnInsert { get { return new DelegateCommand(InsertData); } } public void InsertData(object obj) { Items item = new Items(); item.SItemCode = Guid.NewGuid().ToString(); item.SItemName = obj.ToString(); server.Items.Add(item); server.SubmitChanges(); } public ICommand OnSelectChanged { get { return new DelegateCommand(SelectionChanged); } } private void SelectionChanged(object obj) { if (obj != null) { SeletedItem = obj as Items; } else { SeletedItem = null; } } #region INotifyPropertyChanged 成员 public event PropertyChangedEventHandler PropertyChanged; #endregion }


通过server.SubmitChanges();可以将数据的变化反馈到服务器端的DomainService类中,DomainService类会根据数据集中的数据状态调用相应的方法进行数据处理,需要注意的是silverlight是采用异步处理模式,所以我们要考虑在服务器端的domainservice类中进行数据同步验证处理,以后深入讲解。

5、建立View,进行数据绑定

<Grid x:Name="LayoutRoot" Background="White" DataContext="{Binding Source={StaticResource ItemViewModelDataSource}}"> <sdk:DataGrid AutoGenerateColumns="true" Height="119" HorizontalAlignment="Left" Margin="21,169,0,0" x:Name="dataGrid1" VerticalAlignment="Top" Width="320" ItemsSource="{Binding ItemList, Source={StaticResource ItemViewModelDataSource}}" DataContext="{Binding}" SelectedItem="{Binding SeletedItem, Mode=TwoWay}" > <i:Interaction.Triggers> <i:EventTrigger EventName="SelectionChanged"> <i:InvokeCommandAction Command="{Binding OnSelectChanged, Mode=OneWay}" CommandParameter="{Binding SeletedItem}"/> </i:EventTrigger> </i:Interaction.Triggers> </sdk:DataGrid> <Button Content="查询" Height="23" HorizontalAlignment="Left" Margin="35,55,0,0" x:Name="button1" VerticalAlignment="Top" Width="75" Command="{Binding OnLoad, Mode=OneWay}" /> <Button Content="更新" Height="23" HorizontalAlignment="Left" Margin="116,55,0,0" x:Name="button2" VerticalAlignment="Top" Width="75" Command="{Binding OnUpdate, Mode=OneWay}" /> <Button Content="删除" Height="23" HorizontalAlignment="Left" Margin="197,55,0,0" x:Name="button3" VerticalAlignment="Top" Width="75" Command="{Binding OnDelete, Mode=OneWay}" CommandParameter="{Binding SelectedItem, ElementName=dataGrid1}" /> <TextBox Height="23" HorizontalAlignment="Left" Margin="46,106,0,0" x:Name="textBox1" VerticalAlignment="Top" Width="120" /> <Button Content="添加" Height="23" HorizontalAlignment="Left" Margin="172,106,0,0" x:Name="button4" VerticalAlignment="Top" Width="75" Command="{Binding OnInsert, Mode=OneWay}" CommandParameter="{Binding Text, ElementName=textBox1}" /> </Grid>


整个过程演示了MVVM+WCF RIA架构的实现,其中还有很多内部细节尚未深入,不过整体架构已见雏形!

转载于:https://www.cnblogs.com/oldkingsir/archive/2011/09/07/2365633.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值