金蝶云星空客户端自定义控件插件-WPF实现自定义控件

参考链接1:星空客户端自定义控件开发入门(仅支持到WPF的GUI客户端
参考链接2:客制化控件 + 实现客户端设备集成 (仅支持到WPF的GUI客户端)

金蝶云星空是BS架构,所以有关一些需要与本地交互的功能需求,很难实现;同时云星空也具备客户端使用,但是需要自定义控件实现,这里记录通过WPF实现云星空自定义控件的方式;

创建WPF项目

1.新建项目:选择WPF自定义控件类库(.Net Framework)
图片[1] - 金蝶云星空客户端自定义控件插件-WPF实现自定义控件 - 宋马

2.新建项:选 用户控件(WPF)

WPF用户控件实现代码

1.根据需要拖放控件
图片[2] - 金蝶云星空客户端自定义控件插件-WPF实现自定义控件 - 宋马
2.引用云星空客户端下的类
2.1 C:Program Files (x86)KingdeeK3CloudDeskClientK3CloudClientcontrolpluginsKingdee.BOS.XPF.ControlPlugins.Contracts.dll
(服务端也有此类 WebSite/ClientBin/CustomControl/WPF/Kingdee.BOS.XPF.ControlPlugins.Contracts.dll)
2.2 C:Program Files (x86)KingdeeK3CloudDeskClientK3CloudClientcontrolpluginsKingdee.XPF.CustomControlPlugins.dll
2.3 C:Program Files (x86)KingdeeK3CloudDeskClientK3CloudClientKingdee.BOS.Client.Core.dll
图片[3] - 金蝶云星空客户端自定义控件插件-WPF实现自定义控件 - 宋马
3.封装方法,给云星空插件调用,并且回传数据
3.1 写客户端日志:ClientAppProxy.WriteClientLog(new Exception(string.Format(“previewLaserPicture begin in :{0},{1},{2}”, laserPrintFile, fieldDict, savePath))); 客户端执行日志的查看路径如下:

3.2 回传消息:this.Proxy.FireCustomEvent(new CustomEventArgs(“C_Success”, “C_Success”, “{message:‘WriteString() 成功!’}”)); 其中CustomEventArgs第一个参数为e.Key,第二个参数为e.EventName,第三个参数e.EventArgs,即传递的数据内容;

云星空控件配置

直接在BOSIDE中拖放一个【通用控件–自定义控件】,然后填写属性【程序集】,【类名】,【命名空间】就可以了。

自定义控件部署

编译工程:
自定义控件开发完成后编译项目,并将生成的dll文件压缩成.zip格式压缩文件,然后将*.zip文件改名成*.dll.kdz文件
将自定义控件部署到应用服务器
将第4步生成的*.dll.kdz文件拷贝到服务端【WebSite/ClientBin/CustomControl/WPF】目录下,并且改这个目录下的2个文件MainDownload.xml和MainDownloadList.xml每次更新后将2个文件中的version信息修改保存,以便客户端及时更新到组件,需要中MainDownloadList.xml文件FileList节点中添加一个KDDownloadItem节点内容如下图:
图片[4] - 金蝶云星空客户端自定义控件插件-WPF实现自定义控件 - 宋马
注意:这里要增加节点,内容填写自定义控件类的相关信息
图片[5] - 金蝶云星空客户端自定义控件插件-WPF实现自定义控件 - 宋马

云星空插件

接收自定义控件的数据,根据事件的Key和EventName判断是否我们这个控件的数据(建议命名区分开)
图片[6] - 金蝶云星空客户端自定义控件插件-WPF实现自定义控件 - 宋马
调用自定义控件封装的方法,参数1固定为:DoCustomMethod;参数2为WPF控件封装的方法,参数3为所调用WPF控件封装方法的参数,如果原方法有多个参数,需要整合一个参数的方式,类似于下图JSONArray类型,将参数add到此类型中;

程序调试

1.客户端WPF控件调试:
参考【答疑6】
2.插件调试:启用热更新正常调试
3.客户端http调试:

屏蔽其他端使用该表单

屏蔽其他端使用该表单:
因为本功能仅允许在桌面使用,其他端必须进行功能屏蔽。编写业务插件如下:
public override void PreOpenForm(Core.DynamicForm.PlugIn.Args.PreOpenFormEventArgs e)
{

if (e.Context.ClientType != ClientType.WPF)
{

e.CancelMessage = “不支持桌面应用的功能,请在桌面应用上使用该功能。”;
e.Cancel = true;
}
base.PreOpenForm(e);
}

[或者]显示界面,但不加载第三方ActiveX控件,选择动态加载ActiveX组件的方法。
就是初始化时不加载,控件实现InitThirdPart()方法来初始加载ActiveX控件(类似例子中的WriteString方法),由服务端调用InitThirdPart()才加载控件。
服务端业务插件中AfterBindingData接口重载后判断this.Context.ClientType==ClientType.WPF就调用InitThirdPart()方法,否则就不调用。客制化控件就是给你自己灵活使用的,自己变通想下就可以解决.

答疑篇

【答疑1】:

怎么在客制化控件里控制别的字段, 比如在BOS加了个文本字段FText,怎么在客制化控件桌面客户端代码里为其赋值?

【答】:参考代码:

IKDControlProxy ctl = this.ControlFactoryProxy.GetCmp(key.ToUpper());

if (ctl != null)

{

JObject fldState = new JObject();

fldState[“key”] = “FXXX”;

fldState[“value”] = “xxxxx”;

ctl.UpdateState(fldState);

}

【答疑2】:

写客制化控件插件,出现报错“试图加载格式不正确的程序。”请问这个是什么原因造成和有什么解决方法?

【答】:

注意目标引用的第三方组件是x86的还是x64的。

如果运行在window x86平台的要部署第三方的x86的组件;

如果运行在window x64平台的要部署对于第三方的x64的组件;

如果第三方组件的x86版可以运行在window64平台上,那么你的dll就必须编译成x86的,并且部署x86版本的第三方组件。

如果没有第三方组件引用,就用anycpu编译!
0,检查是否5.0 最新补丁,或者6.0 最新补丁,5.0一定要打最新补丁;
1,检查本地组件路径是否正确;
2,检查配置的命名空间和类名是否正确;
3,检查目标平台是否正确 ,关于微软的x86与x64匹配情况:

必须符合这三种组合之一,不符合的跑不了,这事微软定的规矩:
–3.1、x86win x86/anycpu的k3CloudApp x86第三方组件 x86的第三方依赖组件…;
–3.2、x64win x64/anycpu的k3CloudApp x64第三方组件 x64的第三方依赖组件…;
–3.3、x64win x86的k3CloudApp x86第三方组件 x86的第三方依赖组件…;【6.0最新补丁支持Web登陆后下载x86的k3CloudApp】

如果第三方组件只有x86平台,那么请下载运行x86的客户端来匹配第三方组件:

4,这个方案已经再好几家客户上线应用了;只要正确配置,一定可以运行;

【答疑3】:

客制化控件已经编译完成,如何制作安装包?

【答】:

通过BOSIDE新建解决方案或应用方案,具体方法参考下面教程:

《协同平台之客户端插件扩展篇》【https://vip.kingdee.com/school/97996311328065024 】指引

制作好安装包后,一定要进行本地测试验证:

【验证步骤】

1、安装客户环境匹配的标准产品版本和补丁;

2、安装新构建的二开功能补丁安装包;

3、从桌面启动客户端程序快捷方式,并等待组件更新;

4、更新完成后检查【%Program Files %KingdeeK3CloudDeskClientK3CloudClientcontrolplugins】目录是否正确更新到组件;

5、登入系统执行相关二开业务功能,检验是否正常;

6、如二开功能需要修改重新打包,则验证过程需要从第一步开始再来一遍;

7、以上完成确认无误后,再在系统闲时部署到正式生产环境;

【答疑4】:

如何使用MainDownloadList.xml注册文件配置?

【答】:这种模式为登录界面增量下载模式,在登录界面进行校验下载

一般推荐使用BOSIDE进行注册,或采用答疑3的方法在下载客户端时直接同步下载。

下面介绍MainDownloadList.xml注册文件配置:

1、运行记事本编辑器,打开安装目录【WebSite/ClientBin/CustomControl/WPF/MainDownloadList.xml】的文件。

手工拷贝一个节点(一个文件需要一个节点进行注册如下图)。然后修改绿色的文件名为你的组件名就好了。

2、如果有组件需要更新,请拷贝相关组件到【WebSite/ClientBin/CustomControl/WPF】目录下,并执行上面3.1的步骤,注意更新组件的动作仅在客户端启动时运行一次。同时需要修改注册文件的版本号,以便客户端能够更新到最新组件,如下图:

3、kdz文件部署方法:

在K/3 Cloud服务器安装目录 的【WebSite/ClientBin/CustomControl/WPF】目录下部署二次开发组件,这个目录安装包会自动创建。自定义组件可以用Zip工具压缩为标准Zip格式,后修改后缀名为.kdz, 比如 a.dll -> a.dll.kdz。

3.1、每个组件包括引用组件单独压缩为zip格式的文件,例如:a.dll -> a.dll.zip;

3.2、修改后缀名为.kdz,例如:修改a.zip 文件为 a.dll.kdz;

3.3、配置配置文档,参见 2 或3.1

3.4、部署是注意IIS站点中是否存在MIME类型为.kdz的,如果没有,需要手工加入MIME类型如下:.kdz,application/x-msdownload ;

【答疑5】:

如何使用代码方式配置自定义控件?

【答】:

可以通过放置普通面板,修改xtype方式实现代码化配置自定义控件。编写构造插件方式实现客制化:(备选方案)

1、新建动态表单,拖入面板控件,命名为【FCustomControl】。

2、编写客制化控件服务端表单构建插件,如下代码:

/// <summary>

/// 测试自定义控件构造插件

/// </summary>

public class TestCustomControlCreatePlugIn : AbstractDynamicWebFormBuilderPlugIn

{

    public override void CreateControl(CreateControlEventArgs e)

    {

        base.CreateControl(e);



        if (e.ControlAppearance.Key.EqualsIgnoreCase("FCustomControl"))

        {

            e.Control["Assembly"] = "Kingdee.XPF.CustomControlPlugins";

            e.Control["ClassName"] = "SmartCardReader";

            e.Control["NameSpace"] = "Kingdee.XPF.CustomControlPlugins";

            e.Control["SourcePath"] = "\ClientBin\CustomControl\WPF\Kingdee.XPF.CustomControlPlugins.dll";

            e.Control["xtype"] = "kdcustomcontroldef";

        }

    }

}

【答疑6】:

如何调试自定义的二开控件??

【答】:

1、VS打开代码,并编译Debug版本的二开组件;

2、拷贝debug组件到部署目录【C:Program Files (x86)KingdeeK3CloudDeskClientK3CloudClientcontrolplugins】;

3、在需要的二开代码位置设置断点;

4、启动云星空客户端程序;

5、附加主进程就可以开始调试了;

【答疑7】:

插件中调用DoCustomMethod方法来执行控件方法,为何不成功?

【答】:

调用定制控件接口不成功一般是以下情况,可以参考检查

1、不成功一般是方法名大小写不匹配;

2、参数数量不匹配;

3、参数类型不匹配;

4、上面案例可见是参数2类型有问题;

5、如果实在不想纠结类型,可以把接口都定义为string,然后进行参数校验即可;

6、调用方法再次说明:

6.1、调用方法, 实现定制控件的自定义接口调用
this.View.GetControl(控件标识ID).InvokeControlMethod("DoCustomMethod", "WriteString", args);
6.2、参数说明,第一为方法名,第二为方法参数列表数组如下args说明

// 这里的args参数对应的是一个对象数组,即控件接口参数列表,在C#中如下编码;
//0个参数的情况: var args = new object[1]; args[0] = null;
//1个参数的情况: var args = new object[1]; args[0] = str1;
//2个参数的情况: var args = new object[2]; args[0] = str1; args[1] = str2;
//n个参数的情况: var args = new object[n]; args[0] = str1; args[1] = str2; ... args[n-1] = strn;

【答疑8】:

文章中“ public class SmartCardReader : ContentControl, IKDCustomControl”的ContentControl没有找到,或者没有实现。

【答】:

请仔细参看文章,要求新建WPF类库工程。ContentControl 默认就包含在WPF类库组件System.Windows.Controls命名空间中了。

【答疑9】:

如果只是串口的简单应用,需要写这个复杂的定制控件吗?

【答】:

依据串口应用情况,可以参考以下建议:

1、普通标准串口简单应用,可以参考: 《串口外接设备支持–编程说明》 https://vip.kingdee.com/article/8842

2、存在sdk调用等复杂需求的,高级自定义控件访问本地资源:《客制化控件插件实现客户端设备集成 》

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容