2012-06-19 54 views
2

我有一個DataSet(TZQuery),它有幾個布爾字段,它們有TDBCheckBoxes分配給它們。德爾福。如何在不觸發控制事件的情況下禁用/啓用控件

這些複選框具有分配給它們的「OnClick」事件,每次更改字段值(分配給複選框)時都會觸發它們。

問題是我不需要這些事件觸發,在我做數據集的許多操作過程中。

我試過撥打電話DataSet.DisableControls,但之後我打電話給DataSet.EnableControls

所以我的問題是 - 有沒有辦法來禁用觸發數據感知控件事件。

編輯(放大):

如果有異常情況發生,而我們說保存數據,我有(在保存之前我有過或值)來加載默認值。現在,在加載數據時,會觸發所有這些事件(TDBCheckBoxes和其他數據感知控件),這些操作會執行導致數據滯後甚至有害的數據更改的各種操作,我正在尋找將所有這些事件全部禁用的通用解決方案很短的時間。要做到這一點

+1

如果您正在使用動作列表,那麼您可以簡單地禁用動作列表,同時更新數據庫 –

+0

然後不使用數據庫感知控件,並自己做鏈接... – whosrdaddy

回答

6

大廈紀蓮的帖子:

關閉一切:

遍歷窗體上的每個組件與for循環,如下所示,將屬性更改爲所需的值。

如果你想在以後恢復到原來的屬性值,則必須保存原始值(如OldEvent下面使用。)

編輯:下面的代碼顯示正在討論的關鍵概念。如果在運行時添加或刪除組件,或者如果您想使用絕對最少量的內存,那麼使用動態數組,並且如Pieter所建議的那樣,存儲指向組件的指針而不是索引它們。

const 
    MAX_COMPONENTS_ON_PAGE = 100; // arbitrarily larger than what you'd expect. (Use a dynamic array if this worries you. 
    var 
    OldEvent: Array[0.. MAX_COMPONENTS_ON_PAGE - 1] of TNotifyEvent; // save original values here 
    i: Integer; 
    begin         
    for i := 0 to ComponentCount - 1 do 
    begin 
    if (Components[i] is TCheckBox) then 
     begin 
      OldEvent[i] := TCheckBox(Components[i]).OnClick; // remember old state 
      TCheckBox(Components[i]).OnClick := nil; 
     end 
     else if (Components[i] is TEdit) then 
     begin 
      OldEvent[i] := TEdit(Components[i]).OnClick; // remember old state 
      TEdit(Components[i]).OnClick := nil;   
     end; 
    end; 

恢復到以前的值

for i := 0 to ComponentCount - 1 do 
begin 
    if (Components[i] is TCheckBox) then 
     TCheckBox(Components[i]).OnClick := OldEvent[i] 
    else if (Components[i] is TEdit) then 
     TEdit(Components[i]).OnClick := OldEvent[i]; 
end; 

有可能是所有的if語句的摺疊成一個通用的測試,回答的方式「這種成分有OnClickEvent」 - 但我不知道它是什麼。

希望有人會建設性地批評我的回答(而不是僅僅投票)。但是,希望我上面顯示的是可行的。

+0

我已經使用了這樣的代碼,但我擔心ComponentCount可能會改變,或者以某種方式搞亂了表單中組件的順序,同時正在採取行動 – ertx

+0

ComponentCount不會改變,組件的順序不會改變,除非你在運行時動態添加和刪除組件,AFAIK。 @ertx:感謝您對代碼的必要編輯。 – RobertFrank

+0

@ertx:第二個想法,我不知道你爲什麼添加了Index變量。使用for循環變量「i」作爲下標AFAIK可以正常工作。 – RobertFrank

5

一種方法是如下:

var 
    Event : TNotifyEvent;  
begin 
    Event := myCheckbox.OnClick; 
    try 
    myCheckbox.OnClick := nil; 
    //your code here 
    finally 
    myCheckbox.OnClick := Event; 
    end; 
end; 

HTH

+0

這是行不通的,因爲代碼是模板化的,而我不知道有多少個複選框可能會被分配給一個字段,或者哪個複選框被分配到哪個字段 – ertx

+0

嗯,好的,您能詳細說明您的應用程序如何將複選框分配給字段嗎?從你的評論我明白這些複選框用於網格。我猜對了嗎? –

+0

不,我有一個繼承的形式,其中,複選框在設計時被賦予manualy,但複選框只是一個例子,我與TEdits等有同樣的問題。我會嘗試編輯原始帖子給你對問題有更好的看法。 – ertx

2

TCustomCheckBox的內部設計是它觸發Click方法每次如果更改Checked屬性。通過實際點擊它或者在代碼中設置它。當您撥打EnableControls時會發生這種情況,因爲控件得到更新以顯示數據集中鏈接字段的值。

TButtonControl(這是什麼TCustomCheckBox繼承)有財產ClicksDisabled。使用此代替DisableControls/EnableControls調用(或除此之外)。不幸的是它是受保護的,而不是公開的TCustomCheckBox但你可以用一個小黑客來訪問它:

type 
    TButtonControlAccess = class(TButtonControl) 
    public 
    property ClicksDisabled; 
    end; 

... 

TButtonControlAccess(MyCheckBox1).ClicksDisabled := True; 
// do some dataset stuff 
TButtonControlAccess(MyCheckBox1).ClicksDisabled := False; 

當然,你可以把這個成檢查所有的組件,並設置該屬性的方法,如果從控制繼承TCustomCheckBox或其他一些標準。

相關問題