多層資料庫開發十二:使用資料控制項

來源:互聯網
上載者:User
  第十二章 使用資料控制項
  在資料庫應用程式中,資料控制項是經常要用到的。與前面介紹的資料集構件如TTable、TQuery、TStoredProc、TClientDataSet不同的是,資料控制項都是可視的。也就是說,如果修改了這些構件的屬性,能在表單上馬上反映出來。如果這些構件的Enabled屬性設為True並且資料集的Active屬性也設為True,在設計期就可以看到資料。
12.1 Delphi 4中有哪些資料控制項
  在Delphi 4的IDE中,資料控制項都位於構件選項板的“Data Controls”頁上。下面簡單介紹這些資料控制項:
.TDBGrid以行和列組成的柵格顯示資料。
.TDBNavigator用於對整個資料庫的記錄進行導航,如向前翻一個記錄、向後翻一個記錄、翻到第一個記錄、翻到最後一個記錄等。
.TDBText把欄位的內容作為標籤顯示。
.TDBEdit以編輯框的形式顯示一個欄位的內容。
.TDBMemo以多行文字編輯器的形式顯示備忘欄位的內容。
.TDBImage用於顯示資料庫中的映像欄位。
.TDBListBox以列表框的形式顯示資料。
.TDBComboBox以組合框的形式顯示資料。
.TDBCheckBox以複選框的形式顯示資料。
.TDBRadioGroup以單選框群組方塊的形式顯示資料。
.TDBLookupListBox以列表框的形式顯示這個表的Lookup表的資料。
.TDBLookupComboBox以組合框的形式顯示這個表的Lookup表的資料。
.TDBRichEdit以RTF格式顯示備忘欄位的內容。
.TDBCtrlGrid與TDBGrid相似,但每一個單元都可以分別設定屬性。
.TDBChart以圖表的形式顯示資料庫的資料,用法與TChart相似。
  上述資料控制項在設計期具有資料感知的特點。如果正確設定了DataSource屬性指定了一個資料來源,馬上就能看到資料,而不需要編譯和運行程式。
12.2 資料控制項的基本用法
  這一節介紹資料控制項的基本用法,包括怎樣指定一個資料來源、怎樣編輯和更新資料、怎樣禁止和允許資料重新整理。
12.2.1 指定一個資料來源
  資料控制項必須通過TDataSource構件串連資料集。TDataSource構件扮演的角色實際上就是資料控制項與資料集之間的橋樑。
  首先,把一個資料集構件放到表單或資料模組上,設定它的DatabaseName屬性指定要訪問的資料庫,設定它的TableName屬性指定要訪問的表。
  接著,把一個TDataSource構件放到表單或資料模組上,設定它的DataSet屬性指定資料集。
  然後,把一個資料控制項放到表單上,設定它的DataSource屬性指定TDataSource構件,而這個TDataSource構件的DataSet屬性已經指定了一個資料集。
  最後,設定資料控制項的DataField屬性指定要顯示的欄位。不過,對於TDBGrid、TDBCtrlGrid和TDBNavigator構件來說,不需要設定DataField屬性,因為這幾個控制項是以整個資料集為工作內容的。
12.2.2 編輯和更新資料
  除了TDBNavigator構件外,其他資料控制項都是用來顯示和編輯資料的。這裡要介紹怎樣編輯資料。
  要使使用者能編輯資料,資料集必須進入dsEdit狀態。如果TDataSource的AutoEdit屬性設為False,使用者不能直接編輯資料,除非程式調用Edit函數。
  要使使用者能夠在資料控制項中修改資料,必須把資料控制項的ReadOnly屬性設為False。如果ReadOnly屬性設為True,資料控制項中顯示的資料就是唯讀。
  一般情況下,TDataSource構件的Enabled屬性設為True。如果這個屬性設為False,資料控制項就無法顯示資料,更不能修改資料。
  如果資料集構件的ReadOnly屬性設為True,資料集就是唯讀,使用者在資料控制項中所作的修改不能寫到資料集中。
  除了TDBGrid構件外,當使用者修改了一個欄位的值,還需要把輸入焦點移走,新的資料才寫到資料集中。在移走輸入焦點之前,使用者隨時可以按ESC鍵取消修改。
  在TDBGrid構件建立的柵格中,當使用者修改了一個欄位的值,還需要把輸入焦點移到另一條記錄上,新的資料才寫到資料集中。
12.2.3 禁止和允許資料重新整理
  當程式正在遍曆整個資料集或者搜尋一個特定的記錄時,應當暫時禁止資料控制項重新整理資料,這樣能加快遍曆或搜尋的速度,防止螢幕總是在閃爍。
  調用資料集的DisableControls可以暫時禁止串連這個資料集的資料控制項重新整理資料。DisableControls函數通常在迴圈操作前調用。等迴圈結束後,程式應當立即調用資料集構件的EnableControls函數重新允許重新整理資料。
  為了確保最後總是能恢複重新整理,建議採用Try...Finally結構。這樣,即使在迴圈中出現異常,也可以保證總能調用EnableControls。
  下面的代碼示範了怎樣調用DisableControls和EnableControls函數:
CustTable.DisableControls;
Try
  CustTable.First;
  While not CustTable.EOF Do
  Begin
   ...
   CustTable.Next;
  End;
Finally
  CustTable.EnableControls;
End;
12.2.4 手動重新整理資料
  調用資料集的Refresh可以讀取資料集中最新的資料並重新整理資料控制項,這個功能在多使用者環境尤其有用,因為其他使用者有可能已改變了資料集中的資料。
  有時候,調用Refresh可能會導致意想不到的結果。例如,如果另一個使用者已經刪除了一條記錄,調用Refresh後,這條記錄將從資料控制項中消失。
12.3 顯示單個欄位的資料控制項
  有的資料控制項以資料庫的一個或幾個欄位作為工作內容,如TDBText和TDBEdit,而有的資料控制項以整個資料集為工作內容,如TDBGrid和TDBNavigator。
  顯示單個欄位的資料控制項往往是從一個標準的Windows控制項演化而來的,例如,TDBEdit構件就可以認為是TEdit的資料感知版本。
  圖12.1 用TDBText構件把資料作為標籤顯示
12.3.1 把資料作為標籤顯示
  TDBText構件是一個唯讀資料控制項,它非常類似於TLabel構件和TStaticText構件。TDBText構件能夠把資料作為標籤顯示,用來標註其他控制項。例如,可以用一個TDBText構件在魚的圖片下顯示魚的名稱(Common_Name欄位),12.1所示。
  TDBText構件需要指定一個欄位。當使用者使用導航器或其他手段瀏覽記錄時,TDBText構件顯示的資料將自動變化,因為TDBText構件總是顯示目前記錄的資料。例如,在圖12.1中,當使用者用按一下滑鼠柵格的滾杆兩端的箭頭時,魚的圖片將自動變化,魚的名稱也相應改變,這一切都不需要編程。
  TDBText構件的AutoSize屬性一般要設為True,這是因為欄位的內容長度可能是不同的。如果AutoSize屬性設為False,有些較長的內容可能會被截斷。
12.3.2 顯示和編輯資料
  TDBText構件只能顯示資料,不能編輯資料。要既能顯示資料,又能編輯資料,就要用到TDBEdit構件。TDBEdit可以認為是TEdit的資料感知(Data-Aware)版本。
  例如,有一個TDataSource構件叫CustomersSource,它的DataSet屬性指向一個TTable構件叫CustomersTable。把一個TDBEdit構件放在表單上,其DataSource屬性設為CustomersSource,把它的DataField屬性設為CustNo。這個TDBEdit構件馬上就能顯示CustNo欄位的值。使用者可以在編輯框中鍵入新的值。
12.3.3 顯示和編輯多行文本
  TDBMemo構件是TMemo構件的資料感知版本,可以顯示dBASE和Paradox資料庫中備忘欄位的內容。
  與TDBEdit不同的是,TDBMemo能夠以多行的形式顯示文本,同時也允許使用者鍵入多行文本。
  預設情況下,TDBMemo允許使用者修改它顯示的文本。如果不想讓使用者修改文本,只要把ReadOnly屬性設為True即可。要允許使用者在文本中插入一個定位字元,應當把WantTabs屬性設為True,否則,當使用者按下Tab鍵,將把輸入焦點移走,而不是插入定位字元。
  要限制使用者最多可輸入的字元數,可以設定MaxLength屬性。如果這個屬性設為0,表示沒有限制。
  此外,ScrollBars屬性可以設定要不要加上滾動欄,WordWrap屬性可以設定是否允許自動繞回,Alignment屬性可以設定文本的對齊。
  在運行期,您可以調用CutToClipboard和CopyToClipboard函數把選擇的文本剪下和複製到剪貼簿中,調用PasteFromClipboard能夠粘貼剪貼簿中的文本。如果AutoDisplay屬性設為True,當DataField屬性所指定的欄位的內容改變了時,TDBMemo構件會自動重新整理。如果AutoDisplay屬性設為False,TDBMemo 構件上只顯示欄位名,使用者必須雙擊這個構件或程式調用LoadMemo才能重新整理資料。
12.3.4 以RTF格式顯示文本
  TDBRichEdit構件可以認為是TRichEdit構件的資料感知版本,用於以RTF格式顯示BLOB欄位中的格式化文本。它的用法類似於TDBMemo構件,也能顯示多行文本。
  注意:儘管TDBRichEdit構件能夠顯示RTF格式的文本,並且提供了很強的編輯功能,但是,它本身並沒有提供使用者介面,應用程式必須設計出相應的使用者介面,才能把TDBRichEdit 構件強大的功能發揮出來。
  預設情況下,TDBRichEdit構件允許使用者鍵入新的文本。如果不想讓使用者修改文本,可以把ReadOnly屬性設為True。
  要允許使用者在文本中插入一個定位字元,應當把WantTabs屬性設為True,否則,當使用者按下Tab鍵,將把輸入焦點移走,而不是插入定位字元。
  要限制使用者最多可輸入的字元數,可以設定MaxLength屬性。如果這個屬性設為0,表示沒有限制。
  如果AutoDisplay屬性設為True,當DataField屬性所指定的欄位的內容改變了時,TDBRichEdit構件會自動重新整理。如果AutoDisplay屬性設為False,TDBRichEdit構件上只顯示欄位名,使用者必須雙擊這個構件或程式調用LoadMemo函數才能重新整理資料。
12.3.5 顯示和編輯映像
  TDBImage構件可以認為是TImage構件的資料感知版本,它可以顯示BLOB欄位的內容。TDBImage構件從資料集中檢索了映像後,在本地以DIB格式建立一個副本。
  可以調用CutToClipboard或CopyToClipboard函數把映像剪下或複製到剪貼簿中,調用 PasteFromClipboard可以從剪貼簿中粘貼映像。
  如果Stretch屬性設為True,映像將自動縮放,以適應TDBImage構件的大小,這樣就可能造成映像變形。如果AutoDisplay屬性設為True,當DataField屬性所指定的欄位的內容改變了時,TDBImage構件會自動重新整理。如果這個屬性設為False,TDBImage構件上只顯示欄位名,使用者必須雙擊這個構件才能重新整理資料,當然也可以調用LoadPicture來重新整理資料。
12.4 用列表框和組合框顯示和編輯資料
  有4個特殊的資料控制項可以用列表框和組合框顯示和編輯資料,它們可以認為是標準的列表框和組合框的資料感知版本。下面簡單介紹這4個資料控制項:
.TDBListBox用列表框顯示一組資料,讓使用者從中選擇一個值。
.TDBComboBox用組合框顯示一組資料,讓使用者從中選擇一個值。
.TDBLookupListBox用列表框顯示另一個資料集中的一組資料,讓使用者從中選擇一個值。
.TDBLookupComboBox用組合框顯示另一個資料集中的一組資料,讓使用者從中選擇一個值。
12.4.1 TDBListBox
  TDBListBox構件能夠用列表框顯示一組資料,使用者可以從中選擇一個資料。當使用者瀏覽記錄時,程式將自動在列表框中搜尋與欄位的值匹配的項,如果找到就選擇這一項,12.2所示。
  在列表框中選擇匹配的項反過來,當使用者在列表框中選擇了某個項,程式就自動把目前記錄的該欄位的值改為列表框中選擇的值。當然,要使修改有效還必須調用Post函數。
  要在設計期設定列表框中顯示的項,可以單擊Items屬性邊上的省略符號按鈕開啟一個字串列表編輯器,然後輸入一些字串。
  如果IntegralHeight屬性設為True,列表框的高度將總是項的高度的整數倍。
12.4.2 TDBComboBox
  TDBComboBox構件實際上是TComboBox構件的資料感知版本,它能以組合框的形式顯示一組資料,讓使用者從列表中選擇一個值或直接輸入一個值。
  Items屬性用於設定列表中要顯示的一組資料。在設計期,可以單擊Items屬性邊上的省略符號按鈕開啟一個字串列表編輯器,然後輸入一些字串。
  DropDownCount屬性用於設定當使用者下拉式方塊時不需要加滾動欄就能顯示的項的個數,預設是8,表示使用者下拉式方塊時如果項的個數超過8個才加上滾動欄。如果實際的項數還沒有DropDownCount屬性指定的值多,下拉的組合框的高度自動縮小。
  在Style屬性設為csOwnerDrawFixed的情況下,ItemHeight屬性用於設定項的高度。
12.4.3 顯示另一個資料集中的資料
  TDBLookupListBox構件和TDBLookupComboBox構件分別以列表框和組合框的形式顯示另一個資料集中的資料。
  假設有一個表格叫OrdersTable,其中包含一個CustNo欄位,用於表達客戶的編號,但OrdersTable表中除了客戶的編號外,不包含客戶的其他資訊。而另一個表格假設叫CustomersTable,除了有CustNo欄位外,還有諸如客戶的公司名稱、地址等資訊。
  TDBLookupListBox構件可以實現這樣的功能,當使用者在OrdersTable中瀏覽記錄時,程式首先在CustomersTable中尋找與CustNo欄位匹配的記錄,如果找不到,就從列表中尋找與Company欄位匹配的字串;如果找到,就選擇這一項,12.3所示。
  圖12.3 TDBLookupListBox構件的用法
  當使用者在列表中選擇了一項,程式就在CustomersTable中尋找與字串匹配的Company欄位,如果找到,就用CustNo欄位的值替換OrdersTable表中的CustNo欄位。
12.5 用複選框處理布爾類型的欄位
   TDBCheckBox構件可以認為是TCheckBox構件的資料感知版本,用於處理布爾類型的欄位。例如,可以用一個複選框來表示客戶是否已付帳。
   TDBCheckBox構件實際上是把欄位的值與預設的兩個字串比較,這兩個字串分別由ValueChecked和ValueUnChecked屬性指定。如果欄位的值與ValueChecked屬性指定的字串匹配,就選中複選框。如果欄位的值與ValueUnchecked屬性指定的字串匹配,就不選中複選框。注意:ValueChecked屬性和ValueUnchecked屬性所指定的字串不能相同。
  一般情況下,ValueChecked屬性設為“True”、“Yes”之類的字串,但也可以是其他任意的字串,甚至是一組字串,彼此之間要用分號隔開,例如:
  DBCheckBox1.ValueChecked := 'True;Yes;On';
  上述情況下,當欄位的值只要與其中一個字串匹配,就選中複選框。要說明的是,ValueChecked屬性指定的字串是大小寫敏感的。
  一般情況下,ValueUnchecked屬性設為“False”、“No”之類的字串,但也可以是其他任意的字串,甚至是一組字串,彼此之間用分號隔開。
  如果欄位的值既不與ValueChecked屬性指定的字串匹配,也不與ValueUnchecked屬性指定的字串匹配,複選框就變灰。
12.6 用單選群組方塊限制欄位的值
   TDBRadioGroup構件可以認為是TRadioGroup構件的資料感知版本,它可以限制使用者從一組資料中選擇欄位的值。
   與TRadioGroup構件一樣,首先要設定Items屬性指定單選群組方塊中要顯示哪些項。Items屬性是一個典型的TStrings對象,每一個字串對應著單選群組方塊中的一個按鈕。
  當使用者瀏覽記錄時,如果欄位的值與單選群組方塊中的某個按鈕的標籤匹配,就選擇這個按鈕,12.4所示。
  圖12.4 選擇與CustNo欄位的值匹配的單選框
  反過來,當使用者在單選群組方塊中選擇一個按鈕,程式就用這個按鈕的標籤賦值給DataField屬性指定的欄位。
  如果不想使按鈕的標籤與欄位的值匹配,可以另外指定其他字串,這就要用到Values屬性。Values屬性也是一個TStrings對象,用於指定一組字串。當使用者在單選群組方塊中選擇一個按鈕,程式就用Values屬性中的一個字串賦值給DataField屬性指定的欄位,而不是按鈕的標籤。
12.7 使用TDBGridTDBGrid構件
  以柵格的形式顯示和編輯資料集中的資料。它的外觀很大程度上取決於下面三個因素:
.一是永久的列對象。
.二是永久的欄位對象。
.三是資料集構件的ObjectView屬性將影響ADT和數組欄位的顯示方式。
  對於TDBGrid構件來說,最重要的屬性是Columns,這是一個TDBGridColumns對象,用於管理一組TColumn對象。在設計期,可以開啟一個編輯器建立永久的列對象,然後在對象觀察器中設定列對象的屬性。
12.7.1動態列對象
  如果TDBGridColumns的State屬性設為csDefault,列是動態產生的,列的屬性取決於欄位的屬性。當欄位的屬性發生變化時,列的屬性也跟著變化。
  讓列動態產生的好處是,可以在運行期動態地選擇其他資料集,而不用擔心柵格是否適合於顯示新的資料集。例如,可以用同一個TDBGrid構件先顯示一個Paradox表,再顯示查詢另一個資料庫的結果。
  在設計期,無法直接修改動態列對象的屬性,只能修改欄位對象的屬性,從而間接地修改動態列對象的屬性。
  動態列對象的生存期也取決於欄位對象的生存期。如果資料集沒有建立永久的欄位對象,那麼,當資料集關閉時,所有的動態列對象也將消失。
  注意:如果在運行期把TDBGridColumns的State屬性設為csDefault,將刪除所有的列對象,然後根據資料集中的欄位對象重建列對象。
12.7.2 永久的列對象
  要能夠在設計期自訂柵格,就要用到永久的列對象。建立了永久的列對象後,如果TDBGridColumns的State屬性設為csCustomized,就可以獨立設定每一列的屬性。例如,預設情況下,列的標題顯示欄位的標籤即DisplayLabel屬性,通過修改TColumnTitle的Caption屬性可以重新指定列的標題,而TField的DisplayLabel屬性則不會受到影響。
  TDBGridColumns的State屬性設為csCustomized適合於那些資料集的結構是固定不變的情況。如果需要在運行期切換不同的資料集,就不能把State屬性設為csCustomized。
  要建立永久的列對象,首先要在表單上選擇TDBGrid構件,然後對象觀察器中單擊Columns屬性邊上的省略符號按鈕將開啟12.5所示的編輯器。
  圖12.5 建立永久的列對象
  剛開始的時候,這個編輯器是空白的,這是因為,預設情況下,柵格中的列對象都是動態產生的,還沒有永久的列對象。
  要基於資料集中的每一個欄位分別建立一個永久的列對象,可以單擊滑鼠右鍵,在彈出的菜單中選擇“Add All Fields”命令。
  要建立一個獨立的永久列對象,可以單擊工具列上的(Add New)按鈕。選擇這個剛建立的列對象,然後在對象觀察器中設定FieldName屬性指定一個欄位,設定Caption屬性指定列的標題。
  要刪除一個列對象,可以單擊工具列上的(Delete Selected)按鈕。如果把永久的列都刪掉,柵格反而能顯示資料集中所有的欄位,這是因為,永久的列刪掉以後,Delphi 4會自動把TDBGridColumns的State屬性設為csDefault並且動態產生所有的列。  要調整列在柵格中顯示的順序,可以用滑鼠把列對象前移或後移。
  對於永久的列對象來說,它的屬性的預設值仍然取自於欄位,除非您修改了永久列對象的屬性。例如,預設的情況下,列的標題就是欄位的DisplayLabel屬性。如果修改欄位的DisplayLabel屬性,列的標題將隨之改變。但是,一旦您修改了列對象的Caption屬性,列的標題不再與欄位的DisplayLabel屬性存在聯動關係,它們彼此是獨立的。
  前面講過,建立一個永久的列對象時,需要設定FieldName屬性指定一個欄位。不過,您也可以讓FieldName屬性為空白,此時,TColumn對象的Field屬性將返回NULL,並且該列在柵格中是空白的。空白的列往往用於使用者顯示一些自訂的內容,像或圖表等。
  幾個列對象的FieldName屬性可以設為同一個欄位。由此可見,TDBGrid的FieldCount屬性可能小於柵格的列數
12.7.3 讓使用者編輯資料
  對於永久的列對象來說,可以提供幾種方式讓使用者編輯資料。一是以組合框的方式顯示另一個資料集的資料,二是建立一個靜態列表,三是用省略符號按鈕開啟一個對話方塊。
  要以組合框的方式顯示另一個資料集的資料,首先必須在資料集中增加一個Lookup欄位,然後建立一個永久的列對象,設定它的FieldName屬性指定這個Lookup欄位,並且把它的ButtonStyle屬性設為cbsAuto。經過上述操作後,柵格的效果12.6所示。
  圖12.6 以組合框的形式顯示另一個資料集的資料
  要建立一個靜態列表,不必事先增加一個Lookup欄位,只要先建立一個永久的列對象,把ButtonStyle屬性設為cbsAuto,在對象觀察器中單擊Picklist屬性邊上的省略符號按鈕開啟一個字串列表編輯器,然後依次鍵入一些字串。
  要用一個對話方塊讓使用者選擇資料,必須把列對象的ButtonStyle屬性設為cbsEllipsis。當程式運行時,該列將出現一個省略符號按鈕,單擊這個省略符號按鈕將觸發OnEditButtonClick事件,在處理這個事件的控制代碼中可以開啟一個對話方塊,讓使用者選擇資料。對於映像欄位來說,當使用者單擊省略符號按鈕時,可以顯示一個映像。
12.7.4 在設計期設定列對象的屬性
  列對象的屬性決定了資料在柵格中的顯示方式。在設計期,可以設定它的下列屬性:
.Alignment用於設定資料的對齊,預設值是TField的Alignment。
.ButtonStyle設為cbsAuto表示加上一個組合框。設為cbsEllipsis表示加上一個省略符號按鈕,當使用者單擊此按鈕將觸發OnEditButtonClick。設為cbsNone表示既沒有組合框也沒有省略符號按鈕。
.Color用於設定背景顏色,預設值是TDBGrid的Color。
.DropDownRows 下拉式清單方塊中的項數,預設值是7。
.Expanded如果列對象所對應的欄位是ADT或數組欄位,這個屬性用於控制是否展開。l FieldName用於指定一個欄位,可以讓它空著。
.ReadOnly設為True表示該列是唯讀,不能編輯。
.Width用於設定列的寬度,預設值是TField的DisplayWidth。
.Font用於設定該列中字元的字型,預設值是TDBGrid的Font。
.PickList用於建立一個靜態列表。
.Title這是個TColumnTitle對象,用於設定列的標題。
  其中,TColumnTitle具有下列屬性:
.Alignment用於設定標題的對齊,設為taLeftJustify表示靠左對齊,設為taCenter表示置中,設為taRightJustify表示靠右對齊。
.Caption用於指定標題的文字,預設值是TField的DisplayLabel。
.Color用於設定標題的背景顏色,預設值是TDBGrid的FixedColor。
.Font用於設定標題的字型,預設值是TDBGrid的TitleFont。
12.7.5 顯示ADT和數組欄位的值
  Delphi 4的TDBGrid構件完全支援Oracle 8的對象欄位。
  如果資料集構件的ObjectView屬性設為True,對象欄位就可以展開或摺疊。當對象欄位展開的時候,原來的一列就分為若干列,每一列顯示一個子欄位的值,每一個子欄位所在的列都有自己的標題列,這樣可以明顯地看出欄位之間的內含項目關聯性。當對象欄位摺疊的時候,就只顯示一個字串,該字串列出了每個子欄位的值,彼此之間用逗號隔開。
  如果資料集構件的ObjectView屬性設為False,每個子欄位與對象欄位一樣,都單獨佔一列。
  下面介紹幾個與對象欄位有關的屬性。一是TColumn的Expandable屬性,如果設為True,表示該列是可展開的。二是TColumn的Expanded屬性,用於測試列當前是否已展開。三是TDBGrid的MaxTitleRows屬性,用於設定柵格中最多可出現幾列名。四是TDataSet的ObjectView,這個屬性前面已介紹過了。五是TColumn的ParentColumn屬性,用於返回顯示父欄位的列對象。
   圖12.7示範了ObjectView屬性設為False的情況:
   圖12.7 ObjectView屬性設為False的情況
   圖12.8示範了ObjectView屬性設為True但對象欄位被摺疊的情況:
   圖12.8 ObjectView屬性設為True但對象欄位被摺疊的情況
   圖12.9示範了ObjectView屬性設為True但對象欄位被展開的情況:
   圖12.9 ObjectView屬性設為True但對象欄位被展開的情況
12.7.6 設定柵格的選項
  可以在設計期設定柵格的選項,這就要用到TDBGrid構件的Options屬性。Options屬性是一個集合,可以包含下列元素:
.dgEditing如果包含這個元素(下同),允許使用者修改柵格中的資料;
.dgAlwaysShowEditor柵格自動處於編輯狀態,否則需按F2才進入編輯狀態;
.dgTitles顯示列的標題;
.dgIndicator當前行的最左端將顯示一個4符號;
.dgColumnResize列的寬度可以重設;
.dgColLines列與列之間用線分開;
.dgRowLines行與行之間用線分開;
.dgTabs可以用Tab鍵和Shift+Tab鍵在列與列之間移動輸入焦點;
.dgRowSelect使用者可以選擇一整行,否則就只能選擇一個單元;
.dgAlwaysShowSelection即使輸入焦點移走,選擇的單元仍然保持選擇狀態;
.dgConfirmDelete按Ctrl+Delete刪除一行時將顯示一個確認框,讓使用者確認;
.dgCancelOnExit在柵格退出的時候,任何未決的修改將被取消
.dgMultiSelect使用者可以在柵格中選擇多行,相當於一個複選的列表框。
12.7.7 在運行期響應使用者的動作
  TDBGrid構件具有幾個事件,用於響應使用者的動作。由於柵格是由行和列構成的,因此,在事件控制代碼中,首先要區分當前是在哪一列上。下面列出了這些事件:
.OnCellClick當使用者單擊一個單元時將觸發這個事件。
.OnColEnter當輸入焦點進入某一列時將觸發這個事件。
.OnColExit當輸入焦點離開某一列時將觸發這個事件。
.OnColumnMoved當使用者把某一列移到另一個位置時將觸發這個事件。
.OnDblClick當使用者在柵格中雙擊時將觸發這個事件。
.OnDragDrop當使用者在柵格中釋放被拖曳的對象時將觸發這個事件。
.OnDragOver當使用者拖著一個對象經過柵格時將觸發這個事件。
.OnDrawColumnCell當某個單元需要重畫時將觸發這個事件。
.OnDrawDataCell 在State屬性設為csDefault的情況下,當某個單元需要重畫時將觸發這個事件。
.OnEditButtonClick當使用者單擊省略符號按鈕時將觸發這個事件。
.OnEndDrag當使用者釋放了滑鼠時將觸發這個事件。
.OnEnter當柵格得到輸入焦點時將觸發這個事件。
.OnExit當柵格失去輸入焦點時將觸發這個事件。
.OnKeyDown當使用者按下一個鍵時將觸發這個事件。
.OnKeyPress當使用者按下一個可見的字元鍵時將觸發這個事件。
.OnKeyUp當使用者釋放一個鍵時將觸發這個事件。
.OnStartDrag當使用者開始進行拖放操作時將觸發這個事件。
.OnTitleClick當使用者單擊某一列的標題時將觸發這個事件。
12.7.8 一個特殊的資料庫柵格
  TDBGrid構件的特點是一行只顯示一個記錄,但可以設定每一列的屬性。 TDBCtrlGrid構件的特點是每一行都是一個窗格(TPanel對象),可以在窗格上放一些控制項。例如,可以把一個TDBEdit構件放到窗格上,讓它顯示某個欄位的值,還可以在編輯框的旁邊加一個TLabel構件作為標籤。TDBCtrlGrid的另一個特點是一行上可以有多個窗格,也就是說,一行可以顯示多個記錄,窗格的高度和寬度都是可以調整的。
  首先,要把一個TDBCtrlGrid構件放到表單上,設定它的DataSource屬性指定一個TDataSource構件。剛開始的時候,TDBCtrlGrid構件有三行和一列。
  接著,要把一些資料控制項放到TDBCtrlGrid構件的“設計單元”上,設定這些資料控制項的DataField屬性指定要顯示的欄位。
  “設計單元”通常是最上邊或最左邊的那個單元,與其他單元在外觀上的區別是它沒有斜線底紋。
  注意:只能把資料控制項放到TDBCtrlGrid構件的“設計單元”上,當程式編譯運行後,會自動把“設計單元”上的資料控制項複製到其他單元,每個單元顯示不同的記錄。
  圖12.10示範了TDBCtrlGrid構件的用法:
  圖12.10 TDBCtrlGrid構件的用法
  下面列出了TDBCtrlGrid構件的屬性:
.AllowDelete設為True表示允許刪除記錄。
.AllowInsert設為True表示允許插入記錄。
.ColCount用於設定每一行的窗格數,預設是1。
.Orientation設為goVertical表示從上到下顯示記錄,設為goHorizontal表示從左至右顯示記錄。
.PanelHeight用於設定窗格的高度,預設是72。
.PanelWidth用於設定窗格的寬度,預設是200。
.RowCount用於設定行數,預設是3。
.ShowFocus如果設為True,顯示目前記錄的窗格上有一個虛線邊框。
.SelectedColor用於設定顯示目前記錄的窗格的背景顏色。
12.8 導 航 器
  導航器是用TDBNavigator構件實現的,它可以讓使用者方便地瀏覽和操縱記錄。導航器最多可由10個按鈕組成,包括:
.First第一個記錄;
.Prior前一個記錄;
.Next後一個記錄;
.Last最後一個記錄;
.Insert插入一個空白的記錄;
.Delete刪除目前記錄;
.Edit允許編輯目前記錄;
.Post使未決的編輯操作有效;
.Cancel取消未決的編輯操作;
.Refresh用資料集中的最新的資料重新整理記錄。
  可以根據需要,在導航器上有選擇地顯示部分按鈕,這就要用到VisibleButtons屬性。
  在設計期,可以在對象觀察器中選擇要顯示在導航器上的按鈕。在運行期,您可以通過編程選擇要顯示在導航器上的按鈕。例如,假設要用同一個導航器為兩個資料集導航,其中一個允許使用者編輯資料,另一個不允許使用者編輯資料。當在兩個資料集之間切換時,應當動態地改變導航器上的按鈕,因為對於不允許使用者編輯資料的資料集來說,導航器上不應當出現Insert、Delete、Edit、Post、Cancel和Refresh等按鈕。下面代碼把這些按鈕隱藏:
Procedure TForm1.CustomerCompanyEnter(Sender :TObject);
Begin
If Sender = CustomerCompany then
Begin
DBNavigatorAll.DataSource := CustomerCompany.DataSource;
DBNavigatorAll.VisibleButtons := [nbFirst,nbPrior,nbNext,nbLast];
End
Else
Begin
DBNavigatorAll.DataSource := OrderNum.DataSource;
DBNavigatorAll.VisibleButtons := DBNavigatorAll.VisibleButtons + [nbInsert,nbDelete,nbEdit,nbPost,nbCancel,nbRefresh];
End;
End;
  這裡順便說一下,當同一個導航器需要為幾個資料集導航時,就要動態地設定DataSource屬性。假設表單上有兩個TDataSource構件,分別叫CustomersSource和OrdersSource,它們的DataSet屬性分別指定CustomersTable表和OrdersTable表,另外,表單上有兩個TDBEdit構件,分別叫CustomersEdit和OrdersEdit,它們的DataSource屬性分別指向CustomersSource和OrdersSource。下面這段程式為這兩個TDBEdit構件寫了一個公用的事件控制代碼來處理OnEnter事件,當使用者在CustomersEdit 上編輯時,導航器將為CustomersTable導航,當使用者在OrdersEdit上編輯時,導航器將為OrdersTable導航。
Procedure TForm1. CustomerEditEnter(Sender: TObject);
Begin
If Sender = CustomerEdit Then
   DBNavigatorl.DataSource := CustomerEdit.DataSource;
Else
DBNavigator1.DataSource := OrderEdit.DataSource;
End;
12.9 數 據 源
  TDataSource構件是一個非可視的構件,它充當了資料集和資料控制項之間的橋樑。每一個資料控制項都必須指定一個資料來源(TDataSource構件),相應地,TDataSource構件的DataSet屬性必須指定一個資料集。下面簡單介紹一下TDataSource構件的屬性和事件。
  DataSet屬性用於指定一個資料集。在設計期,可以在對象觀察器中為DataSet屬性選擇一個資料集。在運行期,可以通過代碼動態地選擇資料集。程式樣本如下:
With CustSource Do
Begin
If DataSet = 'Customers' then
DataSet := 'Orders'
Else
DataSet := 'Customers';
End;
  也可以指定另一個表單上的資料集構件,例如:
Procedure TForm2. FormCreate (Sender : TObject);
Begin
DataSource1.Dataset := Form1.Table1;
End;
  一般情況下,TDataSource構件的名稱是無關緊要的。不過,TDataSource構件的名稱應當能反映它所串連的資料集,例如,假設TDataSource構件串連的資料集叫Customers,相應地,TDataSource構件的名稱最好叫CustomersSource。
  Enabled屬性用於控制TDataSource構件是否與資料集串連,設為True表示串連,設為False表示暫時中斷連線。如果Enabled屬性設為False,凡是串連於這個資料來源的資料控制項將變成空白。
  如果AutoEdit屬性設為True,當使用者在資料控制項中鍵入字元時,資料集就自動進入dsEdit狀態。如果AutoEdit屬性設為False,程式必須調用Edit函數才能進入dsEdit狀態。
  當資料集的目前記錄的位置發生變化時將觸發OnDataChange事件,這可能是因為程式調用了Next、Previous、Insert等方法。
  目前記錄的資料將要被更新時將觸發OnUpdateData事件,這可能是因為調用了Post。在處理這個事件的控制代碼中,可以對資料進行校正。
  當State屬性發生變化時將觸發OnStateChange事件。例如,可以用一個標籤動態地顯示當前的狀態。程式樣本如下:
ProcedureTForm1.DataSource1.StateChange(Sender:TObject);
var
S:String;
Begin
Case CustTable.State of
dsInactive: S := 'Inactive';
dsBrowse: S := 'Browse';
dsEdit: S := 'Edit';
dsInsert: S := 'Insert';
dsSetKey: S := 'SetKey';
End;
CustTableStateLabel.Caption := S;
End;
  利用OnStateChange事件也可以動態地允許或禁止按鈕和功能表項目,程式樣本如下:
Procedure Form1.DataSource1.StateChange(Sender: TObject);
Begin
CustTableEditBtn.Enabled := (CustTable.State = dsBrowse);
CustTableCancelBtn.Enabled := CustTable.State in [dsInsert, dsEdit, dsSetKey];
...
End;

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.