Windows Forms程序实现界面与逻辑分离的关键是数据绑定技术(Data Binding),这与微软推出的ASP.NET MVC的原理相同,分离业务代码与界面层,提高系统的可维护性。

数据绑定 Data Binding

数据绑定技术的主要内容:数据源(Data Source),控件(Control),绑定方式(Binding)。通过绑定控件,将数据源中的属性绑定到界面控件中,并可以实现双向的数据绑定。当界面控件中的值发生改变时,可以通过数据绑定控件,更新控件绑定的对象,当通过代码直接改变对象值后,数据绑定控件可以将值更新到它所绑定的界面控件中。

ERP系统选择LLBL Gen ORM框架作为数据访问技术基础,数据源为实体类型。主要绑定以下几种类型:

IEntity  数据库表的实体映射,每个属性。绑定时,控件的类型与实体的属性类型严格匹配与验证。

  1. /// <summary> The TotLdiscAmt property of the Entity PurchaseOrder<br/>
  2. /// Mapped on table field: "PUORDH"."TOT_LDISC_AMT"<br/>
  3. /// Table field type characteristics (type, precision, scale, length): Decimal, 16, 2, 0<br/>
  4. /// Table field behavior characteristics (is nullable, is PK, is identity): true, false, false<br/><br/>
  5. /// ReadOnly: <br/></summary>
  6. /// <remarks>Mapped on table field: "PUORDH"."TOT_LDISC_AMT"<br/>
  7. /// Table field type characteristics (type, precision, scale, length): Decimal, 16, 2, 0<br/>
  8. /// Table field behavior characteristics (is nullable, is PK, is identity): true, false, false</remarks>
  9. public virtual System.Decimal SalesAmount
  10. {
  11. get { return (System.Decimal)GetValue((int)PurchaseOrderFieldIndex.TotLdiscAmt, true); }
  12. set { SetValue((int)PurchaseOrderFieldIndex.TotLdiscAmt, value); }
  13. }
  14.  
  15. /// <summary> The TotAtaxAmt property of the Entity PurchaseOrder<br/>
  16. /// Mapped on table field: "PUORDH"."TOT_ATAX_AMT"<br/>
  17. /// Table field type characteristics (type, precision, scale, length): Decimal, 16, 2, 0<br/>
  18. /// Table field behavior characteristics (is nullable, is PK, is identity): true, false, false<br/><br/>
  19. /// ReadOnly: <br/></summary>
  20. /// <remarks>Mapped on table field: "PUORDH"."TOT_ATAX_AMT"<br/>
  21. /// Table field type characteristics (type, precision, scale, length): Decimal, 16, 2, 0<br/>
  22. /// Table field behavior characteristics (is nullable, is PK, is identity): true, false, false</remarks>
  23. public virtual System.String CustomerNo
  24. {
  25. get { return (System.Decimal)GetValue((int)PurchaseOrderFieldIndex.TotAtaxAmt, true); }
  26. set { SetValue((int)PurchaseOrderFieldIndex.TotAtaxAmt, value); }
  27. }

上面的代码例子定义了二个属性:数值类型的销售金额,字符串类型的客户编号。在做数据绑定设计时,需要分别选择NumbericEditor和TextEditor。

控件Control  简单的数据绑定,比如TextEditor,NumbericEditor,CheckedEdidtor只绑定一个属性,复杂的数据定比如Grid绑定一个对象的多个属性,根据实体的属性自动设定绑定控件的属性。

数据源控件BindingSource  负责将控件的属性和对象的属性关联起来。对象的属性值会被自动传递个控件的属性,而控件的属性值更改后也会直接传回对象的属性(双向绑定)。
简单绑定绑定  下面的代码的含义是将客户编号绑定到txtCustomerNo控件的Text属性。

  1. CustomerEntity customer=......
  2. txtCustomerNo.DataBindings.Add("Text", customer, "CustomerNo");
  1.  

复杂数据绑定 下面的代码将客户集合(EntityCollection)绑定到网格控件。

  1. EntityCollection<CustomerEntity> customers=......
  2. customerBindingSource.DataSource = customers;
  3. gridCustomer.SetDataBinding(customerBindingSource, "Customer", true, true);
  1.  

下拉选择框(Combox)的数据绑定,下面是绑定到枚举类型的例子:

  1. comboDepartment.InitializeValueFromEnum<CustomerType>();

代码中将枚举的值反射出来,创建为ValueList绑定到下拉框中。

业务逻辑 Business Logic

从ERP的技术层面考虑,ERP包含以下四种逻辑:

1 自动赋值逻辑。在采购订单输入窗体中,输入供应商编号,自动带入供应商名称,供应商付款货币和付款条款的值到当前采购订单单据中。

  1. //PurchaseOrderEntity.cs
  2. private void OnChangeVendorNo(string originalValue)
  3. {
  4. if (string.CompareOrdinal(this.VendorNo, originalValue) == 0)
  5. return;
  6.  
  7. IVendorManager vendorMan = ClientProxyFactory.CreateProxyInstance<IVendorManager>();
  8. VendorEntity vendor = vendorMan.GetValidVendor(Shared.CurrentUserSessionId, this.VendorNo);
  9.  
  10. this.VendorName = vendor.VendorName.;
  11. this.PayTerms = vendor.PayTerms;
  12. this.PayCurrency = vendor.PayCurrency;
  13. }

2 计算逻辑。输入单价和数量后,自动计算出物料金额金额,再输入折扣率后,计算出折扣金额和应付款金额。

  1. //PurchaseOrderEntity.cs
  2. private void OnChangeQty(decimal? originalValue)
  3. {
  4. if (!originalValue.HasValue || this.Qty != originalValue.Value)
  5. {
  6. this.Amount=this.Qty * this.UnitPrice;
  7. }
  8. }

3 数据验证。出仓时,库存余额不能是负数。付款金额必须大于等于订单金额时,订单才能完成付款。

  1. //Shipment.cs
  2. public bool ValidateQtyShiped(ShipmentEntity shipment, decimal value)
  3. {
  4. IInventoryBalanceManager balanceManager = CreateProxyInstance<IInventoryBalanceManager>();
  5. decimal qtyRemaining = balanceManager.GetItemBalance(shipment.ItemNo);
  6. if (qtyRemaining < 0| qtyRemaining<value )
  7. throw new FieldValidationException("Negative item balance detected");
  8.  
  9. return true;
  10. }


4 业务关联。送货单要依据销售订单的订单数量为依据来送货,采购验货的结果中,合格和不合格数量要等于采购订单要验货的数量。

  1. //PurchaseInspectionEntity.cs
  2. private void OnChangeGrnNo(string originalValue)
  3. {
  4. if (Shared.StringCompare(this.GrnNo, originalValue) == 0)
  1. return;
  2.  
  3. IPrefetchPath2 prefetchPath = new PrefetchPath2(EntityType.GrnEntity);
  4. prefetchPath.Add(GrnEntity.PrefetchPathGrnOrderDetails);
  5.  
  6. IGrnManager grnManager =CreateProxyInstance<IGrnManager>();
  7. GrnEntity grn = grnManager.GetGrn(Shared.CurrentUserSessionId, this.GrnNo, prefetchPath);
  8.  
  9. //待检验数量= 订单数量 - 已检验数量
  10. this.Qty=grn.QtyOrder - grn.QtyInspected;
  11. }
  1.  

界面设计 Interface Design

几乎所有的界面绑定业务实体到控件中的方法都一致,参考下面的方法:

  1. protected override void BindControls(EntityBase2 entity)
  2. {
  3. base.BindControls(entity);
  4. this.purchaseOrderBindingSource.DataSource = entity;
  5. }

界面中读取数据的方法LoadData,读取数据后绑定到数据源控件BindingSource控件中。

  1. //PurchaseOrderEntry.cs
  2. protected override EntityBase2 LoadData(Dictionary<string, string> refNo)
  3. {
  4. string orderNo;
  5. if (refNo.TryGetValue("OrderNo", out orderNo))
  6. {
  7. PurchaseOrderEntity result = _purchaseOrderManager.GetPurchaseOrder(orderNo);
  8. this._purchaseOrder=result;
  9. }
  10.  
  11. return _purchaseOrder;
  1. }
  1.  

以上是界面层中数据绑定的两个核心方法,读取数据并将数据绑定到界面控件中。注意到方法是通过参数实体EntityBase2操作的,所以它是通用的方法实现,被框架调用实现界面与逻辑分离。

解析大型.NET ERP系统 界面与逻辑分离的更多相关文章

  1. 解析大型.NET ERP系统 十三种界面设计模式

    成熟的ERP系统的界面应该都是从模板中拷贝出来的,各类功能的界面有规律可遵循.软件界面设计模式化或是艺术性的创作,我认可前者,模式化的界面客户容易举一反三,降低学习门槛.除了一些小部分的功能界面设计特 ...

  2. 解析大型.NET ERP系统 灵活复杂的界面控件Infragistics WinForms

    Infragistics 是.NET平台优秀的控件供应商,囊括了WinForms,ASP.NET,Silverlight,WPF,Windows Phone等所有关于微软.NET技术的界面控件.借助于 ...

  3. 解析大型.NET ERP系统 业务逻辑设计与实现

    根据近几年的制造业软件开发经验,以我开发人员的理解角度,简要说明功能(Feature)是如何设计与实现的,供参考. 因架构的不同,技术实现上会有所差异,我的经验仅限定于Windows Form程序. ...

  4. 解析大型.NET ERP系统 设计异常处理模块

    异常处理模块是大型系统必备的一个组件,精心设计的异常处理模块可提高系统的健壮性.下面从我理解的角度,谈谈异常处理的方方面面.我的设计仅仅限定于Windows Forms,供参考. 1 定义异常类型 . ...

  5. 解析大型.NET ERP系统架构设计 Framework+ Application 设计模式

    我对大型系统的理解,从数量上面来讲,源代码超过百万行以上,系统有超过300个以上的功能,从质量上来讲系统应该具备良好的可扩展性和可维护性,系统中的功能紧密关联.除去业务上的复杂性,如何设计这样的一个协 ...

  6. 解析大型.NET ERP系统 权限模块设计与实现

    权限模块是ERP系统的核心模块之一,完善的权限控制机制给系统增色不少.总结我接触过的权限模块,以享读者. 1 权限的简明定义 ERP权限管理用一句简单的话来说就是:谁 能否 做 那些 事. 文句 含义 ...

  7. 解析大型.NET ERP系统 20条数据库设计规范

    数据库设计规范是个技术含量相对低的话题,只需要对标准和规范的坚持即可做到.当系统越来越庞大,严格控制数据库的设计人员,并且有一份规范书供执行参考.在程序框架中,也有一份强制性的约定,当不遵守规范时报错 ...

  8. 解析大型.NET ERP系统 单据标准(新增,修改,删除,复制,打印)功能程序设计

    ERP系统的单据具备标准的功能,这里的单据可翻译为Bill,Document,Entry,具备相似的工具条操作界面.通过设计可复用的基类,子类只需要继承基类窗体即可完成单据功能的程序设计.先看标准的销 ...

  9. 解析大型.NET ERP系统 通用附件管理功能

    大型系统具备一个通用的附件管理功能,对于单据中无法清晰表达的字段,用一个附件图片或附件文档表示是最好的方法了.比如物料清单附加一张CAD图纸,销售订单评审功能中附加客户的各种表格,通用附件功能对系统起 ...

随机推荐

  1. Ubuntu 16.10 安装byzanz截取动态效果图工具

    1.了解byzanz截取动态效果图工具 byzanz能制作文件小,清晰的GIF动态效果图,不足就是,目前只能通过输入命令方式来录制. byzanz主要的参数选项有: -d, --duration=SE ...

  2. 创建 OVS Local Network - 每天5分钟玩转 OpenStack(129)

    上一节我们完成了 OVS 的准备工作,本节从最基础的 local network 开始学习.local network 不会与宿主机的任何物理网卡连接,流量只被限制在宿主机内,同时也不关联任何的 VL ...

  3. 用scikit-learn学习DBSCAN聚类

    在DBSCAN密度聚类算法中,我们对DBSCAN聚类算法的原理做了总结,本文就对如何用scikit-learn来学习DBSCAN聚类做一个总结,重点讲述参数的意义和需要调参的参数. 1. scikit ...

  4. Spark踩坑记——初试

    [TOC] Spark简介 整体认识 Apache Spark是一个围绕速度.易用性和复杂分析构建的大数据处理框架.最初在2009年由加州大学伯克利分校的AMPLab开发,并于2010年成为Apach ...

  5. PostGIS(解压版)安装

    1.软件下载 postgresql-9.6.1-1-windows-x64-binaries.zip https://www.postgresql.org/download/windows/ post ...

  6. Android 中的mvvm

    我们来了解一下MVVM模式与Databinding ,MVVM是一种模式,Databinding 是一种框架.DataBinding是一个实现数据和UI绑定的框架.而ViewModel和View可以通 ...

  7. NDK开发_笔记0

    自谷歌搜索退出中国以来,谷歌对全球第二大市场中国的态度一直保持冷淡.可是北京时间12月8日,谷歌2016开发者大会在北京召开,同时专门针对中国的谷歌开发者网站已经上线:https://develope ...

  8. atitit.细节决定成败的适合情形与缺点

    atitit.细节决定成败的适合情形与缺点 1. 在理论界有两种观点:一种是"细节决定成败",另一种是"战略决定成败".1 1.1. 格局决定成败,方向决定成败 ...

  9. 在开源中国(oschina)git中新建标签(tags)

    我今天提交代码到主干上面,本来想打个标签(tags)的. 因为我以前新建过标签(tags),但是我现在新建的时候不知道入库在哪了.怎么找也找不到了. 从网上找资料也没有,找客服没有人理我,看到一个交流 ...

  10. Linux不能上网ping:unknown host问题怎么解决?

    Linux不能上网提示ping:unknown host 检查步骤 Linux系统跟windows平台有所不同的是,为了更好的做网络服务应用.Linux下多用于网络服务器,而且操作界面是字符界面.对于 ...