Hello,
there is a serious problem concering the consistency of the external representation of the data (the rows and their Content of the grid) with the internal structure (the CDS) in DbAdvGrids.
In the current implementation (Version 2.4.2.7 of dbadvgrid.pas) of the SelectCell method, the Cursor of the CDS is simply moved by the difference of the row number of the newly selected cell (NewRow) to the row number of the old cell (OldRow).
You should never do this! Never make changes to the model based on particularities of a view.
The implementation breaks down as soons as you specify an index for the CDS. After the, any cosistency of the selected row to the Cursor postion is pure coincidence.
Let me ilustrate with a simply example:
We have a CDS with just one Attribute (MyInt) and four records:
MyInt
1
2
3
5
There is also an index active that sorts the records by MyInt with ascending order.
Now, lets select the first record:
MyInt
1 <- Cursor <- selected row
2
3
5
Lets Change the value to 4 and select the second row.
Now, what happens is that as soons as the Change to the record is posted, the CDS Looks like this:
MyInt
2
3
4 <- Cursor
5
A Post() will be called by MoveBy before the Cursor is actually moved.
Since we edited the first row, OldRow = 1, and because we select the second row, NewRow = 2. Thus, the Cursor is moved by NewRow - OldRow = 1. Thus, this is the state after the SelectCell is done:
MyInt
2
3 <- selected row
4
5 <- Cursor
For a quick 'n dirty Workaround I have added and Integer variable "b" to SelectCell and changed the following codeblock:
a := NewRow - OldRow;
FDoNotCountRow := true;
FDoNotCallSelect := true;
try
if DataSetOK and (a <> 0) then
begin
if FAppendOperation and (a = -1) and not FDataLink.DataSet.Modified and (DataSetType = dtSequenced) then
i := FDataLink.DataSet.MoveBy(0)
else if not FInternalMove then
begin
i := FDataLink.DataSet.MoveBy(a);
with:
FDataLink.DataSet.CheckBrowseMode;
b := NewRow - (FDataLink.ActiveRecord + 1);
a := NewRow - OldRow;
FDoNotCountRow := true;
FDoNotCallSelect := true;
try
if DataSetOK and (b <> 0) then
begin
if FAppendOperation and (a = -1) and not FDataLink.DataSet.Modified and (DataSetType = dtSequenced) then
i := FDataLink.DataSet.MoveBy(0)
else if not FInternalMove then
begin
i := FDataLink.DataSet.MoveBy(b);
Additions and changes in bold
This seems to fix the issue, but I don't fully understand the SelectCell method so I don't know if there are any unintended consequences. It is also rather unelegant. You should probably implement something better.