DBAdvGrid - issue with SelectCell and active index

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.

Do you have more details / exact steps how this can be reproduced?
I have retested this here with the latest version of TDBAdvGrid v2.4.4.1 and I could not see an issue when editing a value in the ID column (index) and selecting cells.

The test project can be downloaded here:
http://www.tmssoftware.net/public/CDS_INDEX_DBADVGRID.zip

You are correct. I have set up a clean testing Environment with both the newest Delphi Version and up-to-date TMS components.


It works correctly now. Compared to older versions of the file (where we definitely had this Problem), dbadvgrid.pas had no changes in SelectCell, but Row() is now synchronized with the CDS Cursor. Thus with OldRow := Row the algorithm behaves correctly.

Glad this was fixed after all :-)