[Silverlight]WCF RIA Services+Mef+MVVM实现CRUD(增删改查)示例

做这个示例的目的是为了给学习Silverlight的童鞋一些参考,并希望和大家讨论相关的一些问题,让这个示例更完善。
示例功能说明:实现了雇员的增删改查,雇员表(Employee)和部门表(Department)、雇员类型表(EmployeeType)有外键关联,并和字典表(DataDict)有字典关系

示例参考说明:主要参考了Codeproject上的http://www.codeproject.com/KB/silverlight/IssueVisionForSilverlight.aspx中的相关文章和代码。
示例采用技术说明:
1、采用了WCF RIA Services来和服务器端传输数据,具体来说就是Silverlight项目类型中的WCF RIA Services 类库项目,因为这个更快捷。
2、采用了MVVM设计模式来实现UI元素也UI界面逻辑分离,这个的好处地球人都知道。
3、采用了MEF来对Model和ViewModel、ViewModel和View之间的相互依赖进行解耦。
4、采用了Prism中的部分工具,例如采用CompositePresentationEvent来实现View和ViewModel,ViewModel和ViewModel之间的事件传递,采用NotificationObject作为ViewModel的基类,采用Prism自带的DelegateCommand。
示例项目结构说明:

1、RIAServicesLibrary 解决方案文件夹中是WCF RIA Services的两个项目,服务器端项目RIAServicesLibrary.Web为客户端提供DomainService,来实现实体的增删改查,客户

端项目RIAServicesLibrary通过RiA数据服务链接调用RIAServicesLibrary.Web,实现MVVM中的Models层,并对服务端传递过来的实体进行扩展。
2、SLWCFRIADemo主项目提供员工增删改查操作的所有相关View和ViewModel。
3、SLWCFRIADemo.Common项目顾名思义是公共层,被RIAServicesLibrary和SLWCFRIADemo引用。

在做这个Demo的过程中遇到的一些问题和解决办法:
1、怎样在Datagrid的行上触发ViewModel中的Command?
因Datagrid的ItemsSource指向ViewModel员工集合的属性,而编辑和删除Command是定义在ViewModel中的,所以在Datagrid中直接绑定编辑和删除Command是不起作用的,经查询

Google得出如下解决办法:
首先定义一个类DataContextProxy,故名思意是DataContext的代理类,代码如下:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace SLWCFRIADemo.Controls
{
public class DataContextProxy : FrameworkElement
{
public DataContextProxy()
{
this .Loaded += new RoutedEventHandler(DataContextProxy_Loaded);
}

void DataContextProxy_Loaded( object sender, RoutedEventArgs e)
{
Binding binding
= new Binding();
if ( ! String.IsNullOrEmpty(BindingPropertyName))
{
binding.Path
= new PropertyPath(BindingPropertyName);
}
binding.Source
= this .DataContext;
binding.Mode
= BindingMode;
this .SetBinding(DataContextProxy.DataSourceProperty, binding);
}

public Object DataSource
{
get { return (Object)GetValue(DataSourceProperty); }
set { SetValue(DataSourceProperty, value); }
}

public static readonly DependencyProperty DataSourceProperty =
DependencyProperty.Register(
" DataSource " , typeof (Object), typeof (DataContextProxy), null );


public string BindingPropertyName { get ; set ; }

public BindingMode BindingMode { get ; set ; }

}

}


再在页面中引用这个代理类

  xmlns:my="clr-namespace:SLWCFRIADemo.Controls"

并修改相关代码如下:

  < sdk:DataGridTemplateColumn  Header ="修改 \ 删除"  Width ="100" >
                                                    
< sdk:DataGridTemplateColumn.CellTemplate >
                                                        
< DataTemplate >
                                                            
< StackPanel  Orientation ="Horizontal"  HorizontalAlignment ="Stretch" >
                                                                
< HyperlinkButton  Margin ="5"   Content ="修改"  Command =" {Binding Source={StaticResource DataContextProxy},Path=DataSource.ModifyCommand} " />
                                                                
< HyperlinkButton  Margin ="5"  Content ="删除"  Command =" {Binding Source={StaticResource DataContextProxy},Path=DataSource.DeleteCommand} " />
                                                            
</ StackPanel >
                                                        
</ DataTemplate >
                                                    
</ sdk:DataGridTemplateColumn.CellTemplate >
                                                
</ sdk:DataGridTemplateColumn >

搞定!
2、采用WCF RIA Services怎么处理字典表的问题。
因雇员表和字典表无外键关系,要在DataGrid中显示雇员的性别,不能直接绑定字典表实体,需要在雇员实体中做如下扩展(该扩展在RIAServicesLibrary项目):

   private  EntityRef < DataDict >  employeeSexDict;
         [Association(
" EmployeeSex_DataDict " " EmployeeSex " " DictValue " , IsForeignKey  =   false )]
        
public  DataDict EmployeeSexDict
        {
            
get
            {
                
if  (( this .employeeSexDict  ==   null ))
                {
                    
this .employeeSexDict  =   new  EntityRef < DataDict > ( this " EmployeeSexDict " this .FilterEmployeeSexDict);
                }
                
return   this .employeeSexDict.Entity;
            }
            
set
            {
                DataDict previous 
=   this .EmployeeSexDict;
                
if  ((previous  !=  value))
                {
                    
this .ValidateProperty( " EmployeeSexDict " , value);
                    
if  ((previous  !=   null ))
                    {
                        
this .employeeSexDict.Entity  =   null ;
                    }
                    
if  ((value  !=   null ))
                    {
                        
this .EmployeeSex  =  value.DictValue;
                    }
                    
else
                    {
                        
this .EmployeeSex  =   default ( int );
                    }
                    
this .employeeSexDict.Entity  =  value;
                    
this .RaisePropertyChanged( " EmployeeSexDict " );
                }
            }
        }
        
private   bool  FilterEmployeeSexDict(DataDict entity)
        {
            
if  ( this .EmployeeSex.HasValue)
                
return  (entity.DictValue  ==   this .EmployeeSex.Value);
            
else
                
return   false ;
        }

 

这样就可以直接绑定字典表实体了。
大家对这个示例有什么问题或意见?

更新(2011-05-31):根据Mainz的这篇http://www.cnblogs.com/Mainz/archive/2011/05/27/2059940.html,对代码进行了修改,将查找和分页放在了服务器端,Mainz的代码有点小Bug,我进行了改正,具体请参照最新代码。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值