VS2015开发SAP B1注册ItemEvent报非静态字段引用错误咨询
SAP B1 SDK Grid点击事件捕获 编译报错解决方案
问题背景
基于Visual Studio 2015开发SAP B1 SDK项目,需要实现自定义窗体上的控件点击事件响应逻辑,目标是捕获用户对窗体中Grid控件的点击操作并执行对应业务处理。
项目中Visual Studio自动生成的Main方法初始代码如下:
static void Main(string[] args) { try { Application oApp = null; if (args.Length < 1) { oApp = new Application(); } else { oApp = new Application(args[0]); } Menu MyMenu = new Menu(); MyMenu.AddMenuItems(); oApp.RegisterMenuEventHandler(MyMenu.SBO_Application_MenuEvent); // 原代码中AppEvent注册写法 Application.SBO_Application.AppEvent += new SAPbouiCOM._IApplicationEvents_AppEventEventHandler(SBO_Application_AppEvent); oApp.Run(); } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message); } }
为实现事件捕获,添加如下ItemEvent事件注册代码:
Application.SBO_Application.ItemEvent += new SAPbouiCOM._IApplicationEvents_ItemEventEventHandler(SBO_Application_ItemEvent);
编写完对应的SBO_Application_ItemEvent事件处理方法后,上述注册代码行触发编译错误,提示:非静态字段需要对象引用。
错误原因
项目中自定义封装的Application类里的SBO_Application成员是实例成员,不是静态成员。实例成员归属于类的具体实例,不能直接通过类名Application访问,必须通过已经在Main方法中实例化好的oApp对象访问。
注:原有代码中AppEvent的注册写法本身也存在同样的问题,只是之前可能没有触发编译校验,运行时同样会报错。
修复步骤
- 修正事件注册的对象引用,所有对SBO_Application的访问都通过已实例化的
oApp对象完成,替换原有错误的类名直接访问写法:
// 修正后的事件注册代码 oApp.SBO_Application.AppEvent += new SAPbouiCOM._IApplicationEvents_AppEventEventHandler(SBO_Application_AppEvent); oApp.SBO_Application.ItemEvent += new SAPbouiCOM._IApplicationEvents_ItemEventEventHandler(SBO_Application_ItemEvent);
修改后即可解决编译报错问题。
- 在
SBO_Application_ItemEvent方法中添加Grid点击事件的筛选逻辑,避免无差别处理所有窗体的所有ItemEvent拖慢客户端性能,参考实现如下:
private void SBO_Application_ItemEvent(string FormUID, ref SAPbouiCOM.ItemEvent pVal, out bool BubbleEvent) { BubbleEvent = true; // 筛选条件:点击事件、动作执行后触发(避免重复触发) if (pVal.EventType == SAPbouiCOM.BoEventTypes.et_CLICK && !pVal.BeforeAction) { // 替换为你自定义窗体的FormTypeEx if (pVal.FormTypeEx == "CUSTOM_FORM_001") { // 替换为你窗体中Grid控件的UID if (pVal.ItemUID == "gridMain") { try { SAPbouiCOM.Form currentForm = oApp.SBO_Application.Forms.Item(FormUID); SAPbouiCOM.Grid targetGrid = currentForm.Items.Item("gridMain").Specific; // 此处编写Grid点击后需要执行的业务逻辑 // 示例:获取选中行索引 // int selectedRow = targetGrid.GetDataTableRowIndex(targetGrid.Rows.SelectedRows.Item(0, SAPbouiCOM.BoOrderType.ot_RowOrder)); } catch (Exception ex) { oApp.SBO_Application.StatusBar.SetText(ex.Message, SAPbouiCOM.BoMessageTime.bmt_Short, SAPbouiCOM.BoStatusBarMessageType.smt_Error); } } } } }
注意事项
- 必须加
!pVal.BeforeAction判断,SAP B1的事件会在动作执行前、执行后分别触发一次,不加判断会导致业务逻辑重复执行 - 必须通过
FormTypeEx和ItemUID筛选你需要处理的窗体和控件,全局监听所有ItemEvent会大幅降低SAP客户端响应速度 - 只有当
SBO_Application在自定义Application类中被定义为static静态成员时,才可以直接通过Application.SBO_Application的写法访问,否则必须通过类的实例调用。
内容的提问来源于stack exchange,提问作者memo_star
相关产品推荐
相关产品推荐

