美国银行卡Payoneer注册奖励25美元

  在csdn上承诺要分享一个使用Silverlight+MVVM+MEF实现一个项目,都过去一个月了,我还没开始。。。

最近试着去参考了很多文章和例子,今天就和大家分享一个简单的Sell Through系统,销售管理的那种。

代码下载:http://www.n-pei.com/download/Nicholas.SilverlightSellThrough.zip

使用到的MVVM framework:

http://mvvmlight.codeplex.com/

如果你对MEF没概念,建议看看这里:

http://mef.codeplex.com/

开发环境介绍下:

VS2010英文旗舰版。

MS SQL Server2008 。

一个做零售类型的公司,最基本的几个主档有哪些? 首先是产品(product),是的,它是基础。然后围绕它的有商店(Shop),销售人员(sales),价格(Price),代理商(dealer),以及区域(主要有Province和City)。OK,有了这些基本的思想我们就可以看看它们的关系了。

 

数据模块的创建(Entity Data Model )

首先我们需要创建一个空的ADO.NET Entity Data Model,然后添加上面的Model进去。

 

如果你还没来得及学习Entity Framework 4我建议你可以从这里开始学点基础。

上面的Sellthrough.edmx创建好以后,接下来我们来添加Model以及它们的关系。

在设计模式下的空白处右键,点击添加可以看到添加Model的页面,我们添加一个Model叫Products。

 

接下来是为Products这个Model添加属性字段。分析下它主要应该有code,name,launchdate,createuser,createdate。添加到上面的Model后:

                    

接着是创建其它表,都是以Products为中心,具体的创建过程我这里就不详细描述了。

创建好Models后,我们需要创建model之间的对应关系。以省份和城市之间1:N的关系创建为例说明如何创建:

 在Entity model的空白处右键,选择’Add->association’,如下图:

 

选择好第一个entity和第二个entity,默认的是1:N关系,就直接选择OK,创建完毕。

最终创建好的Entity data model如下:

 

那数据库呢?我们还没有数据库呢。还是得找空白地方,右键,选择’Generate Database from Model…’,如下图:

 

按照提示一步一步操作,就可以生成Sellthrough.edmx.sql,在选择数据库时注意下,因为我们需要新建一个数据库所以要选择New connection:

 

输入数据库名称’sellthrough’,提示你是否新增数据库,选择Yes:

 

完成上面的操作后,数据库脚本就会自动生成了。如下图:

 

接下来在SQL Server Manage Studio中打开这个脚本,执行下,数据库就OK了。

 

Domain Service的创建

在创建好数据库后,接下来我们来创建Domain Services。

有点点击这个project,选择新增,找到Domain Service控件,命名为SellThroughService,点击下一步:

 

选中这些实体后点击OK,Domain Service就创建完成。

到这里服务器端的工作基本上完成了。

接下来我们来看看如何设计客户端的结构。

 

Nicholas.SilverlightSellThrough.Data 是服务器端数据源的扩展部分,Data.Web工程中的WCF  Ria Service会连接到这个工程。同时它还包含一些验证方式的扩展功能等。

例如,Product,我们需要有它字段的验证功能,这些功能就写在Nicholas.SilverlightSellThrough.Data中。

 

Nicholas.SilverlightSellThrough.Common 主要存放了一些通用的方法和接口等。

例如Model的接口, ISellThroughModel.cs。

ViewModelTypes.cs中以常量方式定义了所有的ViewModel。方便后面的工程队ViewModel部分的操作。

Nicholas.SilverlightSellThrough.Model 是为MVVM模式定义的Model部分。

 

目前我们先定义AddNewProduct方法,RemoveProduct,SaveChangeAsync来实现产品的增删改操作。

Nicholas.SilverlightSellThrough.ViewModel:MVVM模式中的ViewModel部分定义在这个工程中。

目前我只定义了三个ViewModel:

 

它们分别实现全部产品的展示,新增产品和修改产品的功能。

最后一个是Nicholas.SilverlightSellThrough:很明显了它就是MVVM中存放View的部分,你可以把所有的View放到View文件夹。

 

 了解了整个架构后,

给大家介绍几个MVVM Light的概念

1. RelayCommand:

Silverlight 4中有了Command这个概念,使得MVVM的模式更加容易。你只需要在ViewModel中定义好你的RelayCommand,然后在View中通过Command来绑定ViewModel中定义好的RelayCommand。

2.Messager

在MVVM Light Toolkit中有个Messager类,就是靠它来让ViewModel和View来通信的。在这个项目中我们定义了AppMessages类来作为通用的一个通信类。

 

using System;
using System.IO;
using System.Windows.Media.Imaging;
using GalaSoft.MvvmLight.Messaging;
using Nicholas.SilverlightSellThrough.Data.Web;

namespace Nicholas.SilverlightSellThrough.Common
{
/// <summary>
/// class that defines all messages used in this application
/// </summary>
public static class AppMessages
{
enum MessageTypes
{
RaiseError,
PleaseConfirm,
EditProduct,
SubmitChanges,
StatusUpdate,
CancelChanges,
ExpriedProduct
}

public static class RaiseErrorMessage
{
public static void Send(Exception ex)
{
Messenger.Default.Send
<Exception>(ex, MessageTypes.RaiseError);
}

public static void Register(object recipient, Action<Exception> action)
{
Messenger.Default.Register
<Exception>(recipient,MessageTypes.RaiseError,action);
}
}

public static class PleaseConfirmMessage
{
public static void Send(DialogMessage dialogMessage)
{
Messenger.Default.Send
<DialogMessage>(dialogMessage,MessageTypes.PleaseConfirm);
}

public static void Register(object recipient, Action<DialogMessage> action)
{
Messenger.Default.Register
<DialogMessage>(recipient, MessageTypes.PleaseConfirm, action);
}
}

public static class StatusUpdateMessage
{
public static void Send(DialogMessage dialogMessage)
{
Messenger.Default.Send
<DialogMessage>(dialogMessage, MessageTypes.StatusUpdate);
}

public static void Register(object recipient, Action<DialogMessage> action)
{
Messenger.Default.Register
<DialogMessage>(recipient, MessageTypes.StatusUpdate, action);
}
}


public static class EditProductMessage
{
public static void Send(Products product)
{
Messenger.Default.Send
<Products>(product, MessageTypes.EditProduct);
}

public static void Register(object recipient, Action<Products> action)
{
Messenger.Default.Register
<Products>(recipient, MessageTypes.EditProduct, action);
}
}

public static class SubmitChangesMessage
{
public static void Send()
{
Messenger.Default.Send
<Boolean>(true, MessageTypes.SubmitChanges);
}

public static void Register(object recipient, Action<Boolean> action)
{
Messenger.Default.Register
<Boolean>(recipient,MessageTypes.SubmitChanges,action);
}
}

public static class CancelChangesMessage
{
public static void Send()
{
Messenger.Default.Send
<Boolean>(true, MessageTypes.CancelChanges);
}

public static void Register(object recipient, Action<Boolean> action)
{
Messenger.Default.Register
<Boolean>(recipient,MessageTypes.CancelChanges,action);
}
}

public static class ExpriedProduct
{
public static void Send()
{
Messenger.Default.Send
<Boolean>(true, MessageTypes.ExpriedProduct);
}

public static void Register(object recipient, Action<Boolean> action)
{
Messenger.Default.Register
<Boolean>(recipient,MessageTypes.ExpriedProduct,action);
}
}
}
}



 

 

3. ICleanup接口:

当显示某个View时,先调用Cleanup方法清除数据:

 

在View中显示所有产品:

首先在数据库中插入几条product数据:

 

我们的目的就是使用MVVM模式把这些数据显示在DataGrid中。

第一步需要在Model中添加GetAllProductsAsync方法:

 public void GetAllProductsAsync()
        {
            PerformQuery<Products>(Context.GetProductsQuery(),GetAllProductsComplete);
        }

 

第二步是在ViewModel工程中添加AllProductsViewModel:

 

在public Commands部分用到的就是上面提到的RelayCommand方法,submitCommand,CancelCommand等。它的作用好比是你在一个xaml页面中添加几个

Submit按钮和Cancel按钮,然后写在它后台的事件。

Load products的代码在ViewModel的构造函数中:

 

注意这里有个selectionchangedCommand,从名字上看得出来它主要是为了让View页面知道当前选中的是哪个product。

第三步也是最后一步就是添加View:

创建一个View,添加一个datagrid,数据绑定如下:

 

注意中间有个trigger,当selectionChanged事件发生时,执行ViewModel中的SelectionChangedCommand方法。

到目前为止我们还未用到MEF,也轮到它登场了。它让程序的扩展性真的是非常好。

在view的后台代码.cs文件中,首先需要使用MEF把AllProductsViewModel导入到View中:

 [Import(ViewModelTypes.AllProductsViewModel)]
        public object ViewModel
        {
            set
            {
                DataContext = value;
            }
        }

 

然后在构造函数中使用CompositionInitializer来把ViewModel加载到页面。

   if (!ViewModelBase.IsInDesignModeStatic)
            { 
              // Use MEF to load the view model
                CompositionInitializer.SatisfyImports(this);
            }

 

最后一步别忘了,使用cleanup接口把当前的这个ViewModel从Messager管道中移除。

运行下看看效果:

 

上面有提到使用那个trigger来设定当前选中的product。那么我们可以使用这个trigger来让当鼠标选中某一行数据时下面显示它的详细信息,并且我们可以编辑它,也就是Editproduct部分。

也是添加Model部分的代码,ModelView部分的代码,最后添加一个View。

效果:

 

修改后保存信息,就可以同步更新到服务器端。

最后是新增页面:

 

具体的实现方法你可以看我提供的源代码。

posted on 2010-08-02 17:19  Nic Pei  阅读(12093)  评论(34编辑  收藏  举报