Lookup表單簡介

來源:互聯網
上載者:User
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方法,使其調用其他的表單,如線上說明中的代碼所示:void Lookup()

{

FormRun FR = New FormRun(New Args("ColorLookup"));

FR.Init();

this.PerformFormLookup(FR);

}

3.Lookup表單是怎麼建立出來的?
表單的建立可以用兩種方式:
a.在AOT中建立
b.用代碼建立
這兩種情形的結果是一樣的,最終在記憶體中都是一個FormRun對象.由於看不到performDBLookup的原始碼,我們只能根據performFormLookup這個方法還推測其原理.
用代碼建立表單AOT中有一個挺好的例子 類SysTableLookup,這個類用於動態建立一個FormRun對象,然後調用表單控制項的performFormLookup方法.下面的代碼是使用該類的用戶端代碼:

void lookup()

{
    Query                   query          = new Query();
    QueryBuildDataSource    queryBuildDataSource;
    QueryBuildRange         queryBuildRange;
// Create an instance of SysTableLookup where 'this' the current Form control.
    SysTableLookup          sysTableLookup = SysTableLookup::newParameters(tableNum(custTable), this);

    ;
// The field to be shown in the lookup form.
    sysTableLookup.addLookupField(fieldNum(custTable, accountNum));
    sysTableLookup.addLookupField(fieldNum(custTable, name));
// Limit and arrange data selection.
    queryBuildDataSource = query.addDataSource(tableNum(custTable));
    queryBuildRange      = queryBuildDataSource.addRange(fieldNum(custTable, accountNum));
    queryBuildRange.value('A..B');
    sysTableLookup.parmQuery(query);
// Perform lookup
    sysTableLookup.performFormLookup();
// do not call super().
//    super()

}

上述代碼就可以建立一個Lookup表單,需要注意的是,如果newParameters的入參是暫存資料表的話,需要用parmTmpBuffer這個函數將當前的暫存資料表傳入進去,否則查不出任何資料.原因很簡單,看一下SysTableLookup這個類的FormRun方法就知道了,它會把傳入的表作為資料來源,如果是實際的物理表這沒任何問題,因為每次都是從資料庫中查詢,但是由於每一個暫存資料表都對應物理磁碟的一個檔案,這樣如果只傳入一個暫存資料表的表名,根據表名它沒有辦法知道去尋找應該對應哪個物理磁碟檔案.該類的FormRun方法用如下語句建立關聯:

 if (tmpBuffer)
    {
        formDataSource.init();
        formDataSource.cursor().setTmp();       // if using non-temp table in tmp mode
        formDataSource.cursor().setTmpData(tmpBuffer);
    }

OK,到這裡,下拉框裡的表單真相大白了,那麼這個表單怎麼會在使用者選擇完之後就自動關掉了,並且會將Grid中的某個特定的值賦值到對應的控制項上那?
這裡用到了FormRun裡的兩個方法,selectMode和selectTarget.
其中selectMode指定取值欄位,selectTarget則指定把值賦值到哪個控制項上.
其函數原型如下:
public final void selectMode( [FormControl _control] )
public final FormControl selectTarget( [FormControl _target] )
selectMode的調用在SysTableLookup中可以找到

formGridControl = formRun.control(idx);
    formGridControl.setFocus();
    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方法中禁用自動查詢功能.範例程式碼如下:void run()
{
    FormStringControl callerControl =
        SysTableLookup::getCallerStringControl(element.args());
    boolean filterLookup = false;
    ;
 
    if (callerControl.text() && callerControl.hasChanged())
    {
        filterLookup = true;
        Common_ds.autoSearch(false);
    }
    super();
    if (filterLookup)
    {
        Common_ds.research();
        Common_LookupField.filter(callerControl.text());
    }
}

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

-

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.