Reputation: 333
I have a grid of entries the user will click on to multi-select for a process. Some of the entries will be invalid based upon values of the first selected row.
I know about DBGrid.SelectedRows.CurrentRowSelected
, but I cannot find a suitable place for checking my conditions to set it to True or False.
Something like this:
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;
I have tried the OnMouseDown
events in Application.OnMessage
and of the DBGrid and the Form, but they do not work, and there is no TBookmarkList.BeforeInsertItem
event. What can I do or must I change?
Upvotes: 3
Views: 6158
Reputation: 11968
I would not make it so complicated.
If the comparison always takes place on the first selection.
The code I use here has hardcoded Value.
No jump around to bookmarks.
// first selection-----------------------------
if DBGrid1.SelectedRows.Count = 1 then begin
CachedIdentity := 'Sonnenbrille'; // Sunglasses
//CachedIdentity := DataSource.DataSet.FieldByName('identity').AsString;
Exit;
end;
Do the comparison
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;
We can see two are selected so
ShowMessage(IntToStr(DBGrid1.SelectedRows.Count));
shows 2
Now we want to select the line
SPORTLICH, ELEGANTE GUCCI SONNENBRILLE
We know a simple Pos() Sonnenbrille
to find SONNENBRILLE
Pos() will be = 0, so a selection-will not take place.
ShowMessage(IntToStr(DBGrid1.SelectedRows.Count));
shows 2 too
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.
Upvotes: 1
Reputation: 30745
If you look at the source of TCustomDBGrid.MouseDown
you'll see how it works out which dataset row (if any) the Mousedown event occurred on. You'll also see the line which leads to the Selection state of the current row being toggled:
if ssCtrl in Shift then
CurrentRowSelected := not CurrentRowSelected
With that in mind, set up an OnMouseUp
event for your grid and put a breakpoint in it.
You should then notice that because of what goes on in the grid's MouseDown
event, by the time your OnMouseUp
event is called, the current row of the grid's dataset has moved to the clicked datarow (see note below). So, at that point you can check whether the current row meets the criteria by which you want to allow the user to select it, and deselect it if it doesn't. I think that answers your specific "how to prevent a row from being selected?"
As a user that deselecting behaviour would annoy me somewhat, so you should probably give the user some indication of why the row has been deselected.
Note: Obviously, the fact that the grid's Mousedown
will result in a call to the dataset's MoveBy
means that the dataset's OnScroll
event has been fired. Depending on exactly what you want to do, the OnScroll
event might be the place to check whether the current datarow meets your selection criteria and, if it doesn't, begin the process of de-selecting it there. In any case, the fact that the dataset should have already be on the datarow where the DBGrid.MouseDown
event was called should save you the trouble of identifying it in your MouseUp
.
Hopefully that will be enough to get you going ...
Upvotes: 2