Lookup窗体简介

Axapta的Lookup窗体提供了一种通用的供用户选择数据的机制,用户可以很方便地实现数据的选择.比如在创建订单的时候在订单主档可很方便地选择客户,订单明细可以方便地选择物料等.
本文试图解释Lookup窗体的实现方式和原理,大多数内容是Axapta的联机帮助的重新组织,部分内容没有参考资料,属于猜测.
准备知识
1.控件类型
Axapta中的窗体控件根据与数据源的绑定情况可以分为三种,绑定控件,非绑定控件和计算控件.
所谓绑定控件是指该控件的DataSource属性指定了某个具体的DataSource,DataField指定了DataSource中的某个字段.
非绑定则没有指定具体的数据源,而ExtendedDataType指定了某个类型.
计算控件是指通过Display或者Edit方法获取的返回值.
2.几个需要关注的控件方法
FormStringControl,FormDateControl等控件类有几个方法用于实现Lookup机制.
Lookup方法,这个方法是在用户点击下拉框时首先触发的方法,该方法的Super()方法会根据该控件与数据源是否绑定分别调用不同的方法:
如果是绑定控件,则会调用performDBLookup方法,performDBLookup继续调用DataSource中字段的Lookup方法.
如果是非绑定控件则会调用performTypeLookup方法,performTypeLookup继续调用PerformFormLookup方法.
从上述描述可以看出根据控件类型,LookUp会走两条不同的路线:
绑定控件: 控件LookUp方法->控件performDBLookup方法->FormDataObject的Lookup方法.
非绑定控件: 控件LookUp方法->控件performTypeLookup方法->控件PerformFormLookup方法.
上述方法的原型如下:
public final void performDBLookup( [fieldId _fieldId, tableId _tableId, selectableDataArea _company] )
public final void performTypeLookup( [int _userType, int _arrayIndex, selectableDataArea _company] )
public void performFormLookup(FormRun _form)
前两个方法是final类型的不允许覆盖.
需要解决的问题
要搞清楚Lookup的原理,需要整明白几件事情:
1.点击下拉框时展示数据的到底是什么?
这个毋庸置疑是一个窗体,也就是一个FormRun的实例对象,由于下拉框一般用Grid展示,所以大部分Form只有一个Grid控件.
2.Grid中展示的数据是如何添加进去的?比如为什么CustTable这个窗体中的客户组字段的Lookup窗体显示了客户组和和说明两个字段而不是其他的字段?
对于绑定控件,在文档中没有找到具体的说明是如何实现的,不过对于Grid中所包含的字段有个说明,是通过表之间的关系来实现的.比如CustTable中的客户组这个字段是CustGroup这个表的外键,于是Grid的字段由表CustGroup的TitleField1和TitleField2这两个属性(分别为CustGroup 和Name),另外就是这两个表之间的关联字段CustGroup,还有表CustGroup的第一个索引.如果这些选项有重复的话会去掉重复的.如果不想用默认的这些属性,那么可以在Field Groups中的AutoLookUp中添加项,这样出来的就是AutoLookUp中的项了.
对于非绑定控件,默认情况下跟绑定控件是一样的,根据控件EDT属性中指定的EDT类型找到对应的表,Grid中包含的字段跟绑定控件类似.
在上述两种情况下,通过设定EDT类型中的FormHelp都可以改变Lookup窗体,比如可以将CustGroupId改成CustGroup等,不过由于Lookup窗体需要特殊定制,一般的窗体是不能满足条件的.
对于非绑定控件,可以重载performFormLookup或者控件的lookup方法,使其调用其他的窗体,如联机帮助中的代码所示:
None.gif void  Lookup()
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gifFormRun FR 
= New FormRun(New Args("ColorLookup"));
InBlock.gif
InBlock.gifFR.Init();
InBlock.gif
InBlock.gif
this.PerformFormLookup(FR);
InBlock.gif
ExpandedBlockEnd.gif}

None.gif

3.Lookup窗体是怎么创建出来的?
窗体的创建可以用两种方式:
a.在AOT中创建
b.用代码创建
这两种情形的结果是一样的,最终在内存中都是一个FormRun对象.由于看不到performDBLookup的源代码,我们只能根据performFormLookup这个方法还推测其原理.
用代码创建窗体AOT中有一个挺好的例子 类SysTableLookup,这个类用于动态创建一个FormRun对象,然后调用窗体控件的performFormLookup方法.下面的代码是使用该类的客户端代码:

None.gif void  lookup()
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    Query                   query          
= new Query();
InBlock.gif    QueryBuildDataSource    queryBuildDataSource;
InBlock.gif    QueryBuildRange         queryBuildRange;
InBlock.gif
// Create an instance of SysTableLookup where 'this' the current Form control.
InBlock.gif
    SysTableLookup          sysTableLookup = SysTableLookup::newParameters(tableNum(custTable), this);
InBlock.gif
InBlock.gif    ;
InBlock.gif
// The field to be shown in the lookup form.
InBlock.gif
    sysTableLookup.addLookupField(fieldNum(custTable, accountNum));
InBlock.gif    sysTableLookup.addLookupField(fieldNum(custTable, name));
InBlock.gif
// Limit and arrange data selection.
InBlock.gif
    queryBuildDataSource = query.addDataSource(tableNum(custTable));
InBlock.gif    queryBuildRange      
= queryBuildDataSource.addRange(fieldNum(custTable, accountNum));
InBlock.gif    queryBuildRange.value(
'A..B');
InBlock.gif    sysTableLookup.parmQuery(query);
InBlock.gif
// Perform lookup
InBlock.gif
    sysTableLookup.performFormLookup();
InBlock.gif
// do not call super().
InBlock.gif
//    super()
InBlock.gif

ExpandedBlockEnd.gif}

None.gif

上述代码就可以创建一个Lookup窗体,需要注意的是,如果newParameters的入参是临时表的话,需要用parmTmpBuffer这个函数将当前的临时表传入进去,否则查不出任何数据.原因很简单,看一下SysTableLookup这个类的FormRun方法就知道了,它会把传入的表作为数据源,如果是实际的物理表这没任何问题,因为每次都是从数据库中查询,但是由于每一个临时表都对应物理磁盘的一个文件,这样如果只传入一个临时表的表名,根据表名它没有办法知道去寻找应该对应哪个物理磁盘文件.该类的FormRun方法用如下语句创建关联:

None.gif   if  (tmpBuffer)
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        formDataSource.init();
InBlock.gif        formDataSource.cursor().setTmp();       
// if using non-temp table in tmp mode
InBlock.gif
        formDataSource.cursor().setTmpData(tmpBuffer);
ExpandedBlockEnd.gif    }

OK,到这里,下拉框里的窗体真相大白了,那么这个窗体怎么会在用户选择完之后就自动关掉了,并且会将Grid中的某个特定的值赋值到对应的控件上那?
这里用到了FormRun里的两个方法,selectMode和selectTarget.
其中selectMode指定取值字段,selectTarget则指定把值赋值到哪个控件上.
其函数原型如下:
public final void selectMode( [FormControl _control] )
public final FormControl selectTarget( [FormControl _target] )
selectMode的调用在SysTableLookup中可以找到

None.gif formGridControl  =  formRun.control(idx);
None.gif    formGridControl.setFocus();
None.gif    formRun.selectMode(formRun.control(controlIdx))
selectTarget这个方法只是在FormRun这个类的联机帮助中找到了它的用法说明,没找到在Lookup窗体怎么使用的,不过可以肯定的是在performFormLookup这个方法中调用了formRun的selectTarget将值赋值到了控件上.
最佳实践:
没有规矩不成方圆,以后俺也关注一下BP,免得被说老土,呵呵.
1.只有系统不能自动生成Lookup窗体时才考虑在AOT中创建自己的Lookup窗体,这些窗体必须以Lookup作为后缀.通常情况下通过定制AutoLookup组就可以满足要求了.
2.如果需要指定Query,显示栏位或者两者都要显示,则应考虑用SysTableLookup类的功能.
3.手动创建的窗体必须与系统自动产生的窗体具有相同的功能,支持查询表达式,根据输入的查询条件自动对焦到相应行.
4.为了避免Lookup窗体闪烁晃动,需要在run方法中禁用自动查询功能.示例代码如下:
None.gif void  run()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    FormStringControl callerControl 
=
InBlock.gif        SysTableLookup::getCallerStringControl(element.args());
InBlock.gif    boolean filterLookup 
= false;
InBlock.gif    ;
InBlock.gif 
InBlock.gif    
if (callerControl.text() && callerControl.hasChanged())
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        filterLookup 
= true;
InBlock.gif        Common_ds.autoSearch(
false);
ExpandedSubBlockEnd.gif    }

InBlock.gif    super();
InBlock.gif    
if (filterLookup)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Common_ds.research();
InBlock.gif        Common_LookupField.filter(callerControl.text());
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}
5.相关属性的设定

AllowCheck

Data source

No

安全检查需要关掉

AllowEdit

Data source

No

不允许编辑

AllowCreate

Data source

No

不允许创建

AllowDelete

Data source

No

不允许删除

OnlyFetchActive

Data source

Yes

只取在Grid中展示的字段

Frame

Design

Border

将不会在窗体上显示属性

WindowType

Design

Popup

-

ShowRowLabel

Grid

No

-

转载于:https://www.cnblogs.com/Farseer1215/archive/2006/12/20/596767.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值