DBGrid:如何防止选择一行?
DBGrid: how to prevent a row from being selected?
我有一个条目网格,用户将点击多个条目select 进行处理。根据第一个 selected 行的值,某些条目将无效。
我知道 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;
我已经尝试了 Application.OnMessage
和 DBGrid 和 Form 中的 OnMouseDown
事件,但是它们不起作用,并且没有 TBookmarkList.BeforeInsertItem
事件。我能做什么或必须改变什么?
如果您查看 TCustomDBGrid.MouseDown
的源代码,您将了解它是如何计算出发生 Mousedown 事件的数据集行(如果有的话)的。您还会看到导致当前行的选择状态被切换的行:
if ssCtrl in Shift then
CurrentRowSelected := not CurrentRowSelected
考虑到这一点,为您的网格设置一个 OnMouseUp
事件并在其中放置一个断点。
然后您应该注意到,由于网格的 MouseDown
事件中发生的事情,当您的 OnMouseUp
事件被调用时,网格数据集的当前行已经移动到被点击的行数据行(见下面的注释)。因此,此时您可以检查当前行是否满足允许用户 select 的条件,如果不满足则取消 select 。我认为这回答了您的具体 "how to prevent a row from being selected?"
作为用户,取消select 的行为会让我有些恼火,因此您可能应该向用户说明为什么该行被取消select。
注意:显然,网格的 Mousedown
将导致调用数据集的 MoveBy
这一事实意味着数据集的 OnScroll
事件已被触发。根据您想要执行的具体操作,OnScroll
事件可能是检查当前数据行是否符合您的 selection 标准的地方,如果不符合,则开始 de-select在那里。在任何情况下,数据集应该已经在调用 DBGrid.MouseDown
事件的数据行上这一事实应该可以避免您在 MouseUp
.
中识别它的麻烦
希望这足以让你继续......
我不会搞得这么复杂。
如果比较总是发生在第一个 selection.
我在这里使用的代码具有硬编码值。
没有跳转到书签。
// 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;
我们可以看到两个 selected
ShowMessage(IntToStr(DBGrid1.SelectedRows.Count));
显示 2
现在我们要 select 行
运动优雅,GUCCI SONNENBRILLE
我们知道一个简单的 Pos() Sonnenbrille
来找到 SONNENBRILLE
Pos() 将是 = 0,所以 selection -不会发生。
ShowMessage(IntToStr(DBGrid1.SelectedRows.Count));
也显示 2
代码:
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.
我有一个条目网格,用户将点击多个条目select 进行处理。根据第一个 selected 行的值,某些条目将无效。
我知道 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;
我已经尝试了 Application.OnMessage
和 DBGrid 和 Form 中的 OnMouseDown
事件,但是它们不起作用,并且没有 TBookmarkList.BeforeInsertItem
事件。我能做什么或必须改变什么?
如果您查看 TCustomDBGrid.MouseDown
的源代码,您将了解它是如何计算出发生 Mousedown 事件的数据集行(如果有的话)的。您还会看到导致当前行的选择状态被切换的行:
if ssCtrl in Shift then
CurrentRowSelected := not CurrentRowSelected
考虑到这一点,为您的网格设置一个 OnMouseUp
事件并在其中放置一个断点。
然后您应该注意到,由于网格的 MouseDown
事件中发生的事情,当您的 OnMouseUp
事件被调用时,网格数据集的当前行已经移动到被点击的行数据行(见下面的注释)。因此,此时您可以检查当前行是否满足允许用户 select 的条件,如果不满足则取消 select 。我认为这回答了您的具体 "how to prevent a row from being selected?"
作为用户,取消select 的行为会让我有些恼火,因此您可能应该向用户说明为什么该行被取消select。
注意:显然,网格的 Mousedown
将导致调用数据集的 MoveBy
这一事实意味着数据集的 OnScroll
事件已被触发。根据您想要执行的具体操作,OnScroll
事件可能是检查当前数据行是否符合您的 selection 标准的地方,如果不符合,则开始 de-select在那里。在任何情况下,数据集应该已经在调用 DBGrid.MouseDown
事件的数据行上这一事实应该可以避免您在 MouseUp
.
希望这足以让你继续......
我不会搞得这么复杂。
如果比较总是发生在第一个 selection.
我在这里使用的代码具有硬编码值。
没有跳转到书签。
// 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;
我们可以看到两个 selected
ShowMessage(IntToStr(DBGrid1.SelectedRows.Count));
显示 2
现在我们要 select 行
运动优雅,GUCCI SONNENBRILLE
我们知道一个简单的 Pos() Sonnenbrille
来找到 SONNENBRILLE
Pos() 将是 = 0,所以 selection -不会发生。
ShowMessage(IntToStr(DBGrid1.SelectedRows.Count));
也显示 2
代码:
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.