2016-04-19 60 views
3

我有一個網格的條目,用戶將點擊進行多選。根據第一個選定行的值,某些條目將無效。DBGrid:如何防止被選中的行?

我知道DBGrid.SelectedRows.CurrentRowSelected,但我找不到合適的地方檢查我的條件,將其設置爲True或False。

事情是這樣的:

var 
    bm: TBookmark; 
    CachedIdentity: String; 
    CanSelect: Boolean; 
begin 
    with dgbSkypeConversations do 
    begin 
    if SelectedRows.Count > 0 then 
    begin 
     DataSource.DataSet.DisableControls; 
     bm := DataSource.DataSet.GetBookmark; 
     CachedIdentity := DataSource.DataSet.FieldByName('identity').AsString; 
     DataSource.DataSet.GotoBookmark(SelectedRows[0]); 
     CanSelect := DataSource.DataSet.FieldByName('identity').AsString <> CachedIdentity; 
     DataSource.DataSet.GotoBookmark(bm); 
     DataSource.DataSet.FreeBookmark(bm); 
     SelectedRows.CurrentRowSelected := CanSelect; 
     DataSource.DataSet.EnableControls; 
    end; 
    end 
end; 

我曾嘗試OnMouseDown事件Application.OnMessage和DBGrid中和形式,但他們沒有工作,也沒有TBookmarkList.BeforeInsertItem事件。我可以做什麼或者我必須改變?

+0

你Q的標題似乎並不符合你的Q的文本描述。你是否試圖阻止用戶選擇網格中的一些行?如果是這樣,爲什麼不阻止他們首先顯示,例如通過在網格的數據集上使用過濾器? –

+0

第一部分:是的。其次,因爲用戶需要查看數據,然後決定選擇什麼,而不是之前......我完成了您可以想象的所有過濾器事項,但我無法更改用戶需求 –

+0

一旦用戶做出第一次選擇(這是您想要禁用*行的點),您可以過濾以刪除不符合條件的行,這從UI角度來看非常乾淨。雖然您可能會以阻止用戶選擇某些行的方式進行破解,但此時您不能以不同的方式繪製它們以指示它們已禁用(不可選)。 –

回答

1

我不會讓它如此複雜。
如果比較始終發生在第一次選擇上。
我在這裏使用的代碼具有硬編碼值。
沒有跳轉到書籤。

// first selection----------------------------- 
if DBGrid1.SelectedRows.Count = 1 then begin 
    CachedIdentity := 'Sonnenbrille'; // Sunglasses 
//CachedIdentity := DataSource.DataSet.FieldByName('identity').AsString; 
    Exit; 
end; 

做比較

if DBGrid1.SelectedRows.CurrentRowSelected then begin 
//if CachedIdentity <> DataSource.DataSet.FieldByName('identity').AsString 
    if Pos(LookingFor,DBGrid1.DataSource.DataSet.FieldByName('haupttxt').AsString)=0 
    then DBGrid1.SelectedRows.CurrentRowSelected := False; 
    ShowMessage(IntToStr(DBGrid1.SelectedRows.Count)); 
end; 

我們可以看到兩個選擇這樣
ShowMessage(IntToStr(DBGrid1.SelectedRows.Count));

顯示

enter image description here

現在,我們要選擇的行

SPORTLICH,ELEGANTE GUCCI SONNENBRILLE

我們知道一個簡單的名次()Sonnenbrille找到SONNENBRILLE波什()將= 0,所以選擇意志沒有發生。

enter image description here

ShowMessage(IntToStr(DBGrid1.SelectedRows.Count));

顯示太

CODE:

var 
CachedIdentity : string; 

procedure TForm2.canSelectedV1; 
begin 
    // first selection----------------------------- 
if DBGrid1.SelectedRows.Count = 1 then begin 
    CachedIdentity := 'Sonnenbrille'; // Sunglasses 
//CachedIdentity := DataSource.DataSet.FieldByName('identity').AsString; 
    Exit; 
end; 
if DBGrid1.SelectedRows.CurrentRowSelected then 
begin 
//if CachedIdentity <> DataSource.DataSet.FieldByName('identity').AsString 
    if Pos(LookingFor,DBGrid1.DataSource.DataSet.FieldByName('haupttxt').AsString)=0 
    then DBGrid1.SelectedRows.CurrentRowSelected := False; 
    ShowMessage(IntToStr(DBGrid1.SelectedRows.Count)); 
end; 
end; 

procedure TForm2.DBGrid1MouseUp(Sender: TObject; Button: TMouseButton; 
    Shift: TShiftState; X, Y: Integer); 
begin 
canSelectedV1; 
end; 

procedure TForm2.DBGrid1KeyUp(Sender: TObject; var Key: Word; 
    Shift: TShiftState); 
begin 
canSelectedV1; 
end; 

end. 
+0

我已經剪了書籤肥胖。但是DBGRid KeyUP和MouseUP事件是我想要的關鍵。非常感謝你。 –

+0

@JoséEduardo:很高興我能幫忙:-) –

2

如果你看看TCustomDBGrid.MouseDown的來源,你會看到它是如何計算Mousedown事件發生在哪個數據集行(如果有的話)。您還可以看到這導致了當前行的選擇狀態的線被切換:

if ssCtrl in Shift then 
    CurrentRowSelected := not CurrentRowSelected 

考慮到這一點,建立一個OnMouseUp事件爲網格將斷點設置在裏面。

然後,您應該注意到,由於網格的MouseDown事件中發生的事情,在您調用OnMouseUp事件時,網格數據集的當前行已移至單擊的數據行(請參閱下面的註釋)。因此,在這一點上,您可以檢查當前行是否符合您希望允許用戶選擇它的標準,如果不符合,則取消選擇它。我認爲這回答你的具體「如何防止被選中的行?」

作爲取消選擇行爲的用戶會讓我有些煩惱,所以您應該給用戶一些指示,說明行被取消選擇的原因。

注意:顯然,網格的Mousedown將導致對數據集的調用MoveBy意味着數據集的事件已被觸發。具體取決於你想要做什麼,OnScroll事件可能是檢查當前數據行是否符合選擇標準的地方,如果不符合,則開始在那裏取消選擇它的過程。在任何情況下,數據集應該已經放在調用DBGrid.MouseDown事件的數據行上的事實將爲您節省在MouseUp中識別它的麻煩。

希望這將足以讓你去...