DBGrid:如何防止选择行?

时间:2016-04-19 16:40:59

标签: delphi 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以及DBGrid和表单中尝试了Application.OnMessage个事件,但它们不起作用,并且没有TBookmarkList.BeforeInsertItem个事件。我能做什么或者我必须改变什么?

2 个答案:

答案 0 :(得分:2)

如果查看TCustomDBGrid.MouseDown的来源,您将看到它如何解决Mousedown事件发生的数据集行(如果有)。您还将看到导致当前行的选择状态被切换的行:

  if ssCtrl in Shift then
    CurrentRowSelected := not CurrentRowSelected

考虑到这一点,为您的网格设置一个OnMouseUp事件并在其中放置一个断点。

然后您应该注意到,由于网格的MouseDown事件发生了什么,当您调用OnMouseUp事件时,网格数据集的当前行已移至单击的数据行(见下面的注释)。因此,此时您可以检查当前行是否符合您希望允许用户选择它的条件,如果不符合,则取消选择它。我认为这会回答你的具体“如何阻止选择一行?”

作为取消选择行为的用户会让我感到烦恼,所以你应该给用户一些关于为什么取消选择行的指示。

注意:显然,网格Mousedown将导致调用数据集的MoveBy,这意味着数据集的OnScroll事件已被触发。根据您想要做的事情,OnScroll事件可能是检查当前数据行是否符合您的选择标准的地方,如果不是,则开始在那里取消选择它的过程。在任何情况下,数据集应该已经在调用DBGrid.MouseDown事件的数据行上,这样可以避免在MouseUp中识别它的麻烦。

希望这足以让你前进......

答案 1 :(得分: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));

显示 2

enter image description here

现在我们要选择

SPORTLICH,ELEGANTE GUCCI SONNENBRILLE

我们知道一个简单的Pos()Sonnenbrille来查找SONNENBRILLE Pos()将 = 0 ,因此不会进行选择。

enter image description here

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

也显示 2

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.