//192.168.73.40:
8000/"/>
开发插件的步骤
插件开发的步骤
1. 定义插件类
打开Visualstudio2012,新建工程:
MyDev.K3.SCM.Stock.Business.PlugIn;
添加引用组件:
Kingdee.BOS
Kingdee.BOS.Core
新建类:
ReceiptEdit,继承自Kingdee.BOS.Core.Bill.PlugIn.AbstractBillPlugIn
2. 分析业务定义重载方法;
这里,我们先简单实现一个HelloWorld:
点击菜单HelloWorld,弹出一个HelloWorld对话框。
点击菜单要重载BarItemClick方法;
3. 引用相关组件(参照组件引用规则);
增加using:
C#
usingKingdee.BOS.Core.Bill.PlugIn;
usingKingdee.BOS.Core.DynamicForm;
usingKingdee.BOS.Core.DynamicForm.PlugIn.Args;
4. 重载方法编码;
重载BarItemClick方法,输入以下代码:
C#
publicoverridevoidBarItemClick(BarItemClickEventArgse)
{
base.BarItemClick(e);
if(e.BarItemKey=="HelloWorld")
{
this.View.ShowMessage("Helloworld!
",MessageBoxType.Notice);
}
}
保存;
5. 设置编译路径,编译组件;
编译路径:
K3Cloud\K3CloudServer\Bin;
6. 打开IDE设计器,配置插件;
先找到单据属性窗口,编辑“采购收料单-_Bill”单据属性:
在插件列表界面,点击注册插件:
(注意该列表中可能已注册有其他插件,这些插件在运行时会动态加载,删除插件可能会导致业务数据错误)
选择插件界面点击浏览:
选择编译好的组件:
勾选插件,确定返回
确定并保存单据。
7. 运行测试;
2、动态表单插件
2.动态表单插件
动态表单插件提供了丰富的接口,通过这些接口可以在插件中对表单编辑和列表界面样式、操作进行控制,也可以对显示数据进行各种处理。
再来回顾一下动态表单元数据结构和继承关系:
动态表单模型包含表单外观和表单业务逻辑,表单外观管理界面控件外观及样式,在模型中由视图(View)来控制,表单业务逻辑管理包括服务、校验器、操作和业务规则等,由模型(Model)来控制。
动态表单外观和逻辑都是在IDE中设置的,设置的数据保存在动态表单模型元数据中,具体由布局元数据(LayoutInfo)记录表单外观数据,由业务元数据(BusinessInfo)记录表单逻辑数据,这2个类分别由View和Model持有。
(图10–2动态表单元模型)
为了方便使用和提高开发效率,我们将动态表单模型分解为各种表单领域模型,同时为各种模型提供了相应插件:
(图10–3领域模型-动态表单模型关系)
动态表单插件分为5大类:
1. 单据插件
2. 列表插件
3. 过滤条件插件
4. 账表插件
5. 动态表单插件
继承关系如下:
(图10–4插件继承关系)
动态表单视图
动态表单视图
前面已经介绍,外观是由视图来管理,我们先看看动态表单视图模型。
根据BOS架构图可以看到,客户端首先向服务发起HTTP请求,服务端由控制器服务接受请求并转送到动态表单模型控制器,再有动态表单控制器访问动态表单视图。
动态表单视图加载外观模型,并从动态表单模型获取数据模型。
动态表单视图提供2个视图接口,IDynamicFormView和IDynamicFormViewService。
IDynamicFormView是视图接口,包含领域模型元数据、多视图模型接口、操作转发指令和通用属性方法。
该接口可由插件直接访问。
IDynamicFormViewService是动态表单内部使用的接口定义,包含Controller消息路由方法,插件开发不需关注。
IDynamicFromView有2个重要属性,BusinessInfo和LayoutInfo,分别表示业务对象逻辑元数据和布局元数据。
包含在IDE中设置的表单的所有信息。
在运行时,客户端发出访问表单请求后,首先读取元数据初始化BusinessInfo和LayoutInfo,View和Model根据元数据定义的界面数据和布局信息展示出表单。
IDynamicFromView接口提供了访问BusinessInfo和LayoutInfo的一些方法,供插件调用以实现业务,例如:
访问菜单,修改控件样式,设置标题,更新界面等。
IDynamicFromView接口同时提供操作控制和调用Model的方法,如:
调用表单服务,执行操作,发送客户端指令,刷新界面,打开表单,动态注册插件等。
本章节通过一些示例做详细介绍。
先看看界面元素的访问。
在实际业务中,经常需要对单据扩展,增加功能,那么就需要访问菜单、字段显示隐藏锁定等。
动态表单模型
动态表单模型
动态表单模型接口:
IDynamicFormModel和IDynamicFormModelService。
设计思想同动态表单视图一样,将逻辑和插件模型分开。
IDynamicFormModel是模型接口,包含领域模型元数据、数据操作方法。
该接口可由插件直接访问。
IDynamicFormModelService是动态表单内部使用的接口定义,插件开发不需关注。
IDynamicFormModel也有BusinessInfo,和IDynamicFromView一样,表示业务对象逻辑元数据。
这里BusinessInfo的意义是根据元数据定义绑定数据。
另外一个重要属性DataObject是当前表单的数据对象。
该数据是个DynamicObject,包含单据头和单据体数据,其中单据体是集合对象DynamicObjectCollection,并且可以有多个.
K/3CloudBOS动态实体类型,默认使用DynamicObject作为数据承载类,可以通过DynamicObjectType.ClrType属性指定自定义类。
但我们要求指定的类型必须派生自DynamicObject。
IDynamicFormModel提供的主要是针对数据进行操作的系列方法,包括:
初始化、新增表单数据、复制数据、删除数据、定位当前分录数据行、设置值等方法。
动态表单插件
动态表单模型是通过插件代理实现业务逻辑,对外部的接口主要是插件,这些接口可以提供给二次开发使用。
命名空间
命名空间
Kingdee.BOS.Core.DynamicForm.PlugIn
主要类及说明:
Class
Description
AbstractDynamicFormDataBinder
动态表单数据绑定器抽象类
AbstractDynamicFormPlugIn
动态表单插件抽象基类
AbstractDynamicWebFormBuilderPlugIn
动态表单页面元数据构建插件
AbstractOperationServicePlugIn
操作服务插件抽象类
主要接口:
Interface
Description
IDynamicFormModelPlugIn
动态表单Model层插件控制接口;实现本接口的插件,可以接收Model层的事件
IDynamicFormViewPlugIn
动态表单View层插件接口;实现本接口的插件可以接收动态表单View层事件
继承体系
继承体系
动态表单插件分4类,单据、基础资料、动态表单和列表。
业务模型
类(插件、服务)
继承自抽象类
表单插件
单据插件
Kingdee.BOS.Core.Bill.PlugIn.AbstractBillPlugIn
基础资料插件
Kingdee.BOS.Core.Base.PlugIn.AbstractBasePlugIn
动态表单插件
Kingdee.BOS.Core.DynamicForm.PlugIn.AbstractDynamicFormPlugIn
列表插件
列表插件
Kingdee.BOS.Core.List.PlugIn.AbstractListPlugIn
单据插件
命名空间
Kingdee.BOS.Core.Bill.PlugIn
继承体系
继承体系
System.Object
Kingdee.BOS.Core.DynamicForm.PlugIn.AbstractDynamicFormPlugIn
Kingdee.BOS.Core.Bill.PlugIn.AbstractBillPlugIn
Kingdee.BOS.Core.Base.PlugIn.AbstractBasePlugIn
接口
视图访问接口
接口名:
IdynamicFormViewPlugIn
动态表单View层插件接口;实现本接口的插件可以接收动态表单View层事件。
Name
Description
AfterBarItemClick
菜单单击事件完成后处理扩展接口
AfterBindData
绑定数据后事件处理后扩展接口
AfterButtonClick
按钮单击之后调用
AfterCopyRow
分录行拷贝后调用
AfterDoOperation
操作完成后调用
AfterEntryBarItemClick
分录菜单单击事件处理扩展接口
AfterF7Select
基础资料选择返回后调用
AfterToolBarItemClick
工具栏单击事件处理扩展接口
BarItemClick
主菜单单击事件处理扩展接口
BeforeBindData
绑定数据前事件处理后扩展接口,主要用于加载数据到界面前对控件状态进行设置
BeforeClosed
页面准备关闭
BeforeDoOperation
操作开始前调用
BeforeF7Select
基础资料界面调出之前抛出
ButtonClick
按钮单击时调用
EntityRowClick
分录行单击事件
EntityRowDoubleClick
分录行双击事件
EntryBarItemClick
分录菜单单击事件处理扩展接口
EntryButtonCellClick
表格按钮单击时调用
FieldLabelClick
字段标题单击事件
FireEntryCheck
单据体列全选事件
ListViewClick
列表控件单击事件
OnInitialize
页面初始化
TabItemSelectedChange
页签控件的页签选中事件
ToolBarItemClick
工具栏单击事件处理扩展接口
TreeDragDrop
KDTree拖拽事件
TreeNodeClick
TreeView节点单击之后调用
TreeNodeDoubleClick
TreeView节点双击之后调用
模型访问接口
接口名:
IdynamicFormModelPlugIn
动态表单Model层插件控制接口;实现本接口的插件,可以接收Model层的事件。
主要包括:
Name
Description
AfterCreateNewData
业务对象创建后的扩展接口
AfterCreateNewEntryRow
新增、插入、多行输入后调用
BeforeUpdateValue
值改变更新前的扩展接口
CreateNewData
创建新业务对象扩展接口,插件可以更加需要自己创建对象
DataChanged
字段值改变后扩展接口
加载机制
动态表单元模型包括外观模型和表单逻辑模型,第一次访问时会先加载元数据,初始化视图和模型对象,初始化页面,然后创建数据包并绑定数据。
对于二次开发提供了一系列插件允许二次开发在加载表单时对视图、模型、数据包及界面进行控制,插件在加载过程中的执行顺序如下:
OnInitialize 页面初始化
CreateNewData 动态表单数据包创建
AfterCreateNewEntryRow 创建分录行后
AfterCreateNewData 动态表单数据包创建后
BeforeBindData 绑定数据前事件
AfterBindData 绑定数据及控件状态
BeforeClosed 页面关闭前
初始化方法
OnInitialize
该插件负责动态表单实例初始化,包括单据Global参数(当然有些参数仅仅在使用时候才获取),动态初始化控件数据源等。
比如,批量修改界面初始化时将允许修改的字段加入到下拉列表。
C#
///
///界面初始化
///
///
publicoverridevoidOnInitialize(Core.DynamicForm.PlugIn.Args.InitializeEventArgse)
{
//根据列表的formid,获取元数据
metadata=(FormMetadata)ServiceHelper.MetaDataServiceHelper.Load
(this.View.Context,this.View.ParentFormView.BillBusinessInfo.GetForm().Id);
//设置标题--!
stringstrTitle=string.Format("{1}-[{0}]",
metadata.GetLayoutInfo().GetFormAppearance().Caption,
this.View.LayoutInfo.GetFormAppearance().Caption);
LocaleValueformTitle=newLocaleValue();
formTitle.Add(newKeyValuePair(this.Context.UserLocale.LCID,strTitle));
this.View.SetFormTitle(formTitle);
Listlist=newList();
//循环检测哪些字段允许批量修改,加入列表
foreach(Fieldfieldinmetadata.BusinessInfo.GetFieldList())
{
if((field.FunControl&Field.FUNCONTROL_BULK_EDIT)!
=Field.FUNCONTROL_BULK_EDIT)continue;
//修改时隐藏的字段不予显示
Appearanceapp=metadata.GetLayoutInfo().GetAppearance(field.Key);
if(app!
=null)
{
if((app.Visible&Appearance.VIS_EDIT)!
=Appearance.VIS_EDIT)
continue;
}
_lstFields.Add(field);
EnumItemitem=newEnumItem();
item.Value=field.Key;
item.Caption=field.Name;
list.Add(item);
}
//排序并将list加入到下拉列表
list=list.OrderBy(p=>p.Caption[this.View.Contex