参考链接1:星空客户端自定义控件开发入门(仅支持到WPF的GUI客户端
参考链接2:客制化控件 + 实现客户端设备集成 (仅支持到WPF的GUI客户端)
金蝶云星空是BS架构,所以有关一些需要与本地交互的功能需求,很难实现;同时云星空也具备客户端使用,但是需要自定义控件实现,这里记录通过WPF实现云星空自定义控件的方式;
创建WPF项目
1.新建项目:选择WPF自定义控件类库(.Net Framework)
![图片[1] - 金蝶云星空客户端自定义控件插件-WPF实现自定义控件 - 宋马](https://pic.songma.com/blogimg/20250708/5f8e5583d0b04faba1b0e8a5da265522.png)

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

WPF用户控件实现代码
1.根据需要拖放控件
![图片[2] - 金蝶云星空客户端自定义控件插件-WPF实现自定义控件 - 宋马](https://pic.songma.com/blogimg/20250708/f07a101da8ca4397bba56616f2f18064.png)
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实现自定义控件 - 宋马](https://pic.songma.com/blogimg/20250708/e2ebff463dcc4037a36aad437bfd063c.png)
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实现自定义控件 - 宋马](https://pic.songma.com/blogimg/20250708/c3516e150dee42c7808bb3535bd2c174.png)
注意:这里要增加节点,内容填写自定义控件类的相关信息
![图片[5] - 金蝶云星空客户端自定义控件插件-WPF实现自定义控件 - 宋马](https://pic.songma.com/blogimg/20250708/665b4c9fcccc437a92f429e248693e39.png)

云星空插件
接收自定义控件的数据,根据事件的Key和EventName判断是否我们这个控件的数据(建议命名区分开)
![图片[6] - 金蝶云星空客户端自定义控件插件-WPF实现自定义控件 - 宋马](https://pic.songma.com/blogimg/20250708/b76388e740064707a6f4b8d20824f821.png)
调用自定义控件封装的方法,参数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调用等复杂需求的,高级自定义控件访问本地资源:《客制化控件插件实现客户端设备集成 》



















暂无评论内容