15.4.2.3 創建主要──明細數據庫應用
TTable部件中MasterSource屬性和MasterFIElds屬性是用於定義兩個數據庫表的一對多的關系。MasterSource屬性指定主表對應的TDataSource部件,MasterFields屬性指定主表和明細表之間建立聯系的字段,主表和明細表之間建立一對多關系時,可能不只是基於一個字段,可能有多個字段。如果有多個字段,那麼在說明MasterFields屬性時,多個字段之間要用分號隔開。如Table1.MasterFields := 'OrderNo;CustNo'。在設計階段可以使用字段連接設計器(Field Link Designer)為兩上表創建一對多的關系,在Object Inspector 中雙擊TTable部件的MasterFields便可以打開Field Link Designer,進行一對多關系的創建。 如創建Customer.DB表和Order.DB表之間的一對多關系時,使用FIEld Link Designer 如圖15.5所示。
圖15.5 使用FIEld Link Designer創建一對多關系
Field Link Designer提供了一種可視化的方法來創建主要──明細表之間的一對多關系。圖中Available Indexes組合框中存放著明細表中的關鍵字段和索引字段,可以選擇索引字段進行連接。在主表中選擇一個用於連接的關鍵字段,然後將其與明細表中相應的關鍵字段連接,單擊Add按鈕,主要──明細表的連接字段將顯示在Joined FIElds列表框中,如:
CustNo->CustNo
15.5 TDataSource部件及其應用
TDataSource部件是開發數據庫應用程序中用到的非常重要的部件,它是連接數據集部件TTable或TQuery和數據浏覽部件的橋梁。TDataSource部件本身十分簡單,它所擁有的屬性、事件和方法都比較少,在使用該部件時無需作太多的工作,它主要是為數據浏覽部件服務的,如果在應用程序中沒有使用數據浏覽部件,我們也沒有必要為應用程序設置TDataSource部件。
15.5.1 TDataSource部件的屬性
TDataSource部件除了其他部件都擁有的Name屬性和Tag屬性之外,主要有下面幾個屬性:
DataSet屬性:該屬性說明TDataSource部件從中獲取數據的數據集的名字,它可以是TTable部件的名字,也可以是TQuery部件的名字,甚至還可以指定其他窗體內的數據集作為該屬性的值,如在下面的程序中我們指定窗體Form2中的table1作為窗體Form1中的DataSource1的DataSet屬性值:
TForm1.Formcreate(Sender : Tobject);
Begin
DataSource1.DataSet := Form2.Table1;
end;
Enable屬性:Enable屬性可以暫時性地切斷TDataSource部件和與之相連的數據集部件的連接。這是一個布爾型變量。當它的值為False時,TDataSource部件和數據集部件的連接被切斷,且所有與TDataSource部件相連的數據浏覽部件中將變為一片空白,不顯示任何數據信息。當Enabled的值變為True時,TDataSource部件和數據集部件的連接恢復,且與TDataSource部件相連的數據浏覽部件恢復顯示數據。不過要實現上述這些功能,一般不使用TDataSource部件的Enabled屬性,而是調用數據集部件的DisableControls方法和EnableControls 方法,因為調用這兩個方法可以方便地控制與數據集部件相連的所有TDataSource部件以及與TDataSource部件相連的數據浏覽部件。
AutoEdit屬性:這是一個布爾型變量,它用於說明是否將與TDataSource部件相連的數據集置於編輯狀態。當AutoEdit的值為True時,應用程序運行時,與TDataSource相連的數據集部件自動地被設置成編輯狀態,當用戶在與TDataSource部件相連的數據浏覽部件中輸入新的值時,數據集部件中的記錄也隨之改變。如果AutoEdit的值為False,用戶想通過數據浏覽部件或程序修改數據集中的記錄,必須要調用數據集部件的Edit方法,將其置為編輯狀態之後才能夠進行。
15.5.2 TDataSource部件的事件
TDataSource部件具有三個事件:
● OnDataChange事件
● OnStateChange
● OnUpdataData
OnDataChange事件:當與TDataSource相連的數據集中的記錄指針的位置發生改變時,該事件就被觸發,也就是說當程序調用數據集部件的Next、Previous、Insert、Append等方法導致記錄指針的位置發生改變時,便會觸發該事件。該事件一般用於保持應用中多個部件之間的同步。
OnUpdataData事件:當數據集部件中當前記錄將要被修改時,觸發該事件。例如在程序調用post方法之後但在修改後的數據記錄真正被寫回磁盤中的數據庫文件之前觸發該事件,在應用中使用非數據浏覽部件時要它與數據集保持同步時常使用該事件進行相關的處理。
OnStateChange事件:當與TDataSource部件相連的數據集部件的狀態發生改變時,便觸發該事件。因為數據集部件的State屬性標明了數據集部件當前所處的狀態,當數據集的狀態發生變化時,使用該事件進行有關的處理是很有用的,在一個具體的應用中,數據集部件的狀態常常是頻繁地變化的,為了跟蹤數據集部件的狀態變化,可以用下面例子中的程序代碼將數據集部件當前的狀態顯示在一個標簽上:
TForm1.DataSource1OnStateChange(Sender : Tobject);
var
S : String;
begin
Case Table1,State of
dsInactive : S := 'Inactive';
dsBrowse : S := 'Browse';
dsEdit : S := 'Edit';
dsInsert : S := 'SetKey';
dsSetKey : S := 'SetKey';
end;
Label1.Caption := S;
end;
類似地我們也可以通過檢測數據集部件的狀態來控制有關的按鈕和菜單項是否有效。例如:在一個應用窗體中有一個InsertBtn按鈕,用於控制向數據集部件table1對應的數據庫表中插入記錄;還有一個CancelBtn按鈕用於控制是否取消用戶對當前記錄的修改或插入新記錄。下面的程序代碼根據Table1的狀態來控制這兩個按鈕的功能(是否有效,在窗體是否變灰暗)。
Form1.DataSource1OnStateChange(Sender : Tobject);
begin
InsertBtn.Enabled := (Table1.State = dsBrowse);
CancelBtn.Enabled := Table1.State in [dsInsert,dsEdit,dsSetKey]
end;
上面的代碼中,當Table1處於浏覽狀態(Browse狀態時),用戶是不能夠向數據庫表中插入新記錄的,此時InsertBtn按鈕將變灰暗即無效。當Table1不處於Browse狀態時,InsertBtn按鈕有效,用戶是可以向表中插入新記錄。同理,只有當Table1處於特入狀態(Insert狀態)或編輯狀態(Edit狀態)或查找狀態(SetKey狀態)時,CancelBtn按鈕才有效,也即用戶可以取消當前插入的記錄、修改當前的記錄以及查找到的結果等。